jspwiki-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ajaqu...@apache.org
Subject svn commit: r682144 [4/4] - in /incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/src/com/ecyrd/jspwiki: auth/authorize/ auth/login/ auth/permissions/ auth/user/ content/
Date Sun, 03 Aug 2008 12:17:35 GMT
Modified: incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/user/XMLUserDatabase.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/user/XMLUserDatabase.java?rev=682144&r1=682143&r2=682144&view=diff
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/user/XMLUserDatabase.java
(original)
+++ incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/src/com/ecyrd/jspwiki/auth/user/XMLUserDatabase.java
Sun Aug  3 05:17:34 2008
@@ -1,21 +1,22 @@
 /* 
- JSPWiki - a JSP-based WikiWiki clone.
+    JSPWiki - a JSP-based WikiWiki clone.
 
- Copyright (C) 2001-2005 Janne Jalkanen (Janne.Jalkanen@iki.fi)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.  
  */
 package com.ecyrd.jspwiki.auth.user;
 
@@ -24,17 +25,12 @@
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Properties;
-import java.util.Set;
+import java.util.*;
 
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
+import org.w3c.dom.*;
 import org.xml.sax.SAXException;
 
 import com.ecyrd.jspwiki.NoRequiredPropertyException;
@@ -42,6 +38,7 @@
 import com.ecyrd.jspwiki.auth.NoSuchPrincipalException;
 import com.ecyrd.jspwiki.auth.WikiPrincipal;
 import com.ecyrd.jspwiki.auth.WikiSecurityException;
+import com.ecyrd.jspwiki.util.Serializer;
 
 /**
  * <p>Manages {@link DefaultUserProfile} objects using XML files for persistence.
@@ -73,6 +70,8 @@
     
     private static final String DEFAULT_USERDATABASE = "userdatabase.xml";
 
+    private static final String ATTRIBUTES_TAG = "attributes";
+    
     private static final String CREATED           = "created";
     
     private static final String EMAIL             = "email";
@@ -83,8 +82,12 @@
 
     private static final String LAST_MODIFIED     = "lastModified";
     
+    private static final String LOCK_EXPIRY    = "lockExpiry";
+
     private static final String PASSWORD          = "password";
 
+    private static final String UID = "uid";
+
     private static final String USER_TAG          = "user";
 
     private static final String WIKI_NAME         = "wikiName";
@@ -185,6 +188,19 @@
     }
 
     /**
+     * {@inheritDoc}
+     */
+    public UserProfile findByUid( long uid ) throws NoSuchPrincipalException
+    {
+        UserProfile profile = findByAttribute( UID, Long.toString( uid ) );
+        if ( profile != null )
+        {
+            return profile;
+        }
+        throw new NoSuchPrincipalException( "Not in database: " + uid );
+    }
+
+    /**
      * Looks up and returns the first {@link UserProfile}in the user database
      * that matches a profile having a given wiki name. If the user database
      * does not contain a user with a matching attribute, throws a
@@ -209,6 +225,7 @@
      * contain any profiles, this method will return a zero-length
      * array.
      * @return the WikiNames
+     * @throws WikiSecurityException In case things fail.
      */
     public Principal[] getWikiNames() throws WikiSecurityException
     {
@@ -216,7 +233,7 @@
         {
             throw new IllegalStateException( "FATAL: database does not exist" );
         }
-        Set principals = new HashSet();
+        SortedSet<Principal> principals = new TreeSet<Principal>();
         NodeList users = c_dom.getElementsByTagName( USER_TAG );
         for( int i = 0; i < users.getLength(); i++ )
         {
@@ -232,7 +249,7 @@
                 principals.add( principal );
             }
         }
-        return (Principal[])principals.toArray( new Principal[principals.size()] );
+        return principals.toArray( new Principal[principals.size()] );
     }
     
     /**
@@ -345,7 +362,9 @@
             for( int i = 0; i < nodes.getLength(); i++ )
             {
                 Element user = (Element)nodes.item( i );
-                io.write( "<" + USER_TAG + " ");
+                io.write( "    <" + USER_TAG + " ");
+                io.write( UID );
+                io.write( "=\"" + user.getAttribute( UID ) + "\" " );
                 io.write( LOGIN_NAME );
                 io.write( "=\"" + user.getAttribute( LOGIN_NAME ) + "\" " );
                 io.write( WIKI_NAME );
@@ -360,7 +379,19 @@
                 io.write( "=\"" + user.getAttribute( CREATED ) + "\" " );
                 io.write( LAST_MODIFIED );
                 io.write( "=\"" + user.getAttribute( LAST_MODIFIED ) + "\" " );
-                io.write(" />\n");
+                io.write( LOCK_EXPIRY );
+                io.write( "=\"" + user.getAttribute( LOCK_EXPIRY ) + "\" " );
+                io.write( ">" );
+                NodeList attributes = user.getElementsByTagName( ATTRIBUTES_TAG );
+                for ( int j = 0; j < attributes.getLength(); j++ )
+                {
+                    Element attribute = (Element)attributes.item( j );
+                    String value = extractText( attribute );
+                    io.write( "\n        <" + ATTRIBUTES_TAG + ">" );
+                    io.write( value );
+                    io.write( "</" + ATTRIBUTES_TAG + ">" );
+                }
+                io.write("\n    </" +USER_TAG + ">\n");
             }
             io.write("</users>");
             io.close();
@@ -411,16 +442,6 @@
             }
         }
     }
-    
-    /**
-     * Determines whether the user database shares user/password data with the
-     * web container; always returns <code>false</code>.
-     * @see com.ecyrd.jspwiki.auth.user.UserDatabase#isSharedWithContainer()
-     */
-    public boolean isSharedWithContainer()
-    {
-        return false;
-    }
 
     /**
      * @see com.ecyrd.jspwiki.auth.user.UserDatabase#rename(String, String)
@@ -492,31 +513,46 @@
         String index = profile.getLoginName();
         NodeList users = c_dom.getElementsByTagName( USER_TAG );
         Element user = null;
-        boolean isNew = true;
         for( int i = 0; i < users.getLength(); i++ )
         {
             Element currentUser = (Element) users.item( i );
             if ( currentUser.getAttribute( LOGIN_NAME ).equals( index ) )
             {
                 user = currentUser;
-                isNew = false;
                 break;
             }
         }
+        
+        boolean isNew = false;
+        
         Date modDate = new Date( System.currentTimeMillis() );
-        if ( isNew )
+        if( user == null )
         {
+            // Create new user node
             profile.setCreated( modDate );
             log.info( "Creating new user " + index );
             user = c_dom.createElement( USER_TAG );
             c_dom.getDocumentElement().appendChild( user );
             setAttribute( user, CREATED, c_format.format( profile.getCreated() ) );
+            isNew = true;
+        }
+        else
+        {
+            // To update existing user node, delete old attributes first...
+            NodeList attributes = user.getElementsByTagName( ATTRIBUTES_TAG );
+            for ( int i = 0; i < attributes.getLength(); i++ )
+            {
+                user.removeChild( attributes.item( i ) );
+            }
         }
+        
         setAttribute( user, LAST_MODIFIED, c_format.format( modDate ) );
         setAttribute( user, LOGIN_NAME, profile.getLoginName() );
         setAttribute( user, FULL_NAME, profile.getFullname() );
         setAttribute( user, WIKI_NAME, profile.getWikiName() );
         setAttribute( user, EMAIL, profile.getEmail() );
+        Date lockExpiry = profile.getLockExpiry();
+        setAttribute( user, LOCK_EXPIRY, lockExpiry == null ? "" : c_format.format( lockExpiry
) );
 
         // Hash and save the new password if it's different from old one
         String newPassword = profile.getPassword();
@@ -525,7 +561,24 @@
             String oldPassword = user.getAttribute( PASSWORD );
             if ( !oldPassword.equals( newPassword ) )
             {
-                setAttribute( user, PASSWORD, SHA_PREFIX + getHash( newPassword ) );
+                setAttribute( user, PASSWORD, getHash( newPassword ) );
+            }
+        }
+        
+        // Save the attributes as as Base64 string
+        if ( profile.getAttributes().size() > 0 )
+        {
+            try
+            {
+                String encodedAttributes = Serializer.serializeToBase64( profile.getAttributes()
);
+                Element attributes = c_dom.createElement( ATTRIBUTES_TAG );
+                user.appendChild( attributes );
+                Text value = c_dom.createTextNode( encodedAttributes );
+                attributes.appendChild( value );
+            }
+            catch ( IOException e )
+            {
+                throw new WikiSecurityException( "Could not save user profile attribute.
Reason: " + e.getMessage() );
             }
         }
 
@@ -542,7 +595,8 @@
 
     /**
      * Private method that returns the first {@link UserProfile}matching a
-     * &lt;user&gt; element's supplied attribute.
+     * &lt;user&gt; element's supplied attribute. This method will also
+     * set the UID if it has not yet been set.
      * @param matchAttribute
      * @param index
      * @return the profile, or <code>null</code> if not found
@@ -562,16 +616,52 @@
             Element user = (Element) users.item( i );
             if ( user.getAttribute( matchAttribute ).equals( index ) )
             {
-                UserProfile profile = new DefaultUserProfile();
+                UserProfile profile = newProfile();
+                
+                // Parse basic attributes
+                profile.setUid( parseLong( user.getAttribute( UID ) ) );
+                if ( profile.getUid() == UID_NOT_SET )
+                {
+                    profile.setUid( generateUid( this ) );
+                }
                 profile.setLoginName( user.getAttribute( LOGIN_NAME ) );
                 profile.setFullname( user.getAttribute( FULL_NAME ) );
                 profile.setPassword( user.getAttribute( PASSWORD ) );
                 profile.setEmail( user.getAttribute( EMAIL ) );
+                
+                // Get created/modified timestamps
                 String created = user.getAttribute( CREATED );
                 String modified = user.getAttribute( LAST_MODIFIED );
-                
                 profile.setCreated( parseDate( profile, created ) );                  
                 profile.setLastModified( parseDate( profile, modified ) );              
   
+                
+                // Is the profile locked?
+                String lockExpiry = user.getAttribute( LOCK_EXPIRY );
+                if ( lockExpiry == null || lockExpiry.length() == 0 )
+                {
+                    profile.setLockExpiry( null );
+                }
+                else
+                {
+                    profile.setLockExpiry( new Date( Long.parseLong( lockExpiry ) ) );
+                }
+                
+                // Extract all of the user's attributes (should only be one attributes tag,
but you never know!)
+                NodeList attributes = user.getElementsByTagName( ATTRIBUTES_TAG );
+                for ( int j = 0; j < attributes.getLength(); j++ )
+                {
+                    Element attribute = (Element)attributes.item( j );
+                    String serializedMap = extractText( attribute );
+                    try
+                    {
+                        Map<String,? extends Serializable> map = Serializer.deserializeFromBase64(
serializedMap );
+                        profile.getAttributes().putAll( map );
+                    }
+                    catch ( IOException e )
+                    {
+                        log.error( "Could not parse user profile attributes!", e );
+                    }
+                }
 
                 return profile;
             }
@@ -580,6 +670,29 @@
     }
 
     /**
+     * Extracts all of the text nodes that are immediate children of an Element.
+     * @param element the base element
+     * @return the text nodes that are immediate children of the base element, concatenated
together
+     */
+    private String extractText( Element element )
+    {
+        String text = "";
+        if ( element.getChildNodes().getLength() > 0 )
+        {
+            NodeList children = element.getChildNodes();
+            for ( int k = 0; k < children.getLength(); k++ )
+            {
+                Node child = children.item( k );
+                if ( child.getNodeType() == Node.TEXT_NODE )
+                {
+                    text = text + ((Text)child).getData();
+                }
+            }
+        }
+        return text;
+    }
+
+    /**
      *  Tries to parse a date using the default format - then, for backwards
      *  compatibility reasons, tries the platform default.
      *  
@@ -625,6 +738,16 @@
         for( int i = 0; i < users.getLength(); i++ )
         {
             Element user = (Element) users.item( i );
+            
+            // Sanitize UID (and generate a new one if one does not exist)
+            String uid = user.getAttribute( UID ).trim();
+            if ( uid == null || uid.length() == 0 || "-1".equals( uid ) )
+            {
+                uid = String.valueOf( generateUid( this ) );
+                user.setAttribute( UID, uid );
+            }
+            
+            // Sanitize dates
             String loginName = user.getAttribute( LOGIN_NAME );
             String created = user.getAttribute( CREATED );
             String modified = user.getAttribute( LAST_MODIFIED );
@@ -656,7 +779,7 @@
     }
     
     /**
-     * Private method that sets an attibute value for a supplied DOM element.
+     * Private method that sets an attribute value for a supplied DOM element.
      * @param element the element whose attribute is to be set
      * @param attribute the name of the attribute to set
      * @param value the desired attribute value

Added: incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/src/com/ecyrd/jspwiki/content/PageRenamer.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/src/com/ecyrd/jspwiki/content/PageRenamer.java?rev=682144&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/src/com/ecyrd/jspwiki/content/PageRenamer.java
(added)
+++ incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/src/com/ecyrd/jspwiki/content/PageRenamer.java
Sun Aug  3 05:17:34 2008
@@ -0,0 +1,374 @@
+/* 
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.  
+ */
+package com.ecyrd.jspwiki.content;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+
+import com.ecyrd.jspwiki.*;
+import com.ecyrd.jspwiki.attachment.Attachment;
+import com.ecyrd.jspwiki.parser.JSPWikiMarkupParser;
+import com.ecyrd.jspwiki.parser.MarkupParser;
+import com.ecyrd.jspwiki.providers.ProviderException;
+
+/**
+ *  Provides page renaming functionality.  Note that there used to be
+ *  a similarly named class in 2.6, but due to unclear copyright, the
+ *  class was completely rewritten from scratch for 2.8.
+ *
+ *  @since 2.8
+ */
+public class PageRenamer
+{
+
+    private static final Logger log = Logger.getLogger( PageRenamer.class );
+    
+    private boolean m_camelCase = false;
+    
+    /**
+     *  Renames a page.
+     *  
+     *  @param context The current context.
+     *  @param renameFrom The name from which to rename.
+     *  @param renameTo The new name.
+     *  @param changeReferrers If true, also changes all the referrers.
+     *  @return The final new name (in case it had to be modified)
+     *  @throws WikiException If the page cannot be renamed.
+     */
+    public String renamePage( WikiContext context, 
+                              String renameFrom, 
+                              String renameTo, 
+                              boolean changeReferrers )
+        throws WikiException
+    {
+        //
+        //  Sanity checks first
+        //
+        if( renameFrom == null || renameFrom.length() == 0 )
+        {
+            throw new WikiException( "From name may not be null or empty" );
+        }
+        if( renameTo == null || renameTo.length() == 0 )
+        {
+            throw new WikiException( "To name may not be null or empty" );
+        }
+       
+        //
+        //  Clean up the "to" -name so that it does not contain anything illegal
+        //
+        
+        renameTo = MarkupParser.cleanLink( renameTo.trim() );
+        
+        if( renameTo.equals(renameFrom) )
+        {
+            throw new WikiException( "You cannot rename the page to itself" );
+        }
+        
+        //
+        //  Preconditions: "from" page must exist, and "to" page must not yet exist.
+        //
+        WikiEngine engine = context.getEngine();
+        WikiPage fromPage = engine.getPage( renameFrom );
+        
+        if( fromPage == null )
+        {
+            throw new WikiException("No such page "+renameFrom);
+        }
+        
+        WikiPage toPage = engine.getPage( renameTo );
+        
+        if( toPage != null )
+        {
+            throw new WikiException("Page already exists "+renameTo);
+        }
+        
+        //
+        //  Options
+        //
+        
+        m_camelCase = TextUtil.getBooleanProperty( engine.getWikiProperties(), 
+                                                   JSPWikiMarkupParser.PROP_CAMELCASELINKS,

+                                                   m_camelCase );
+        
+        //
+        //  Do the actual rename by changing from the frompage to the topage, including
+        //  all of the attachments
+        //
+        
+        engine.getPageManager().getProvider().movePage( renameFrom, renameTo );
+        
+        if( engine.getAttachmentManager().attachmentsEnabled() )
+        {
+            engine.getAttachmentManager().getCurrentProvider().moveAttachmentsForPage( renameFrom,
renameTo );
+        }
+
+        //
+        //  Add a comment to the page notifying what changed.  This adds a new revision
+        //  to the repo with no actual change.
+        //
+        
+        toPage = engine.getPage( renameTo );
+        
+        if( toPage == null ) throw new InternalWikiException("Rename seems to have failed
for some strange reason - please check logs!");
+
+        toPage.setAttribute( WikiPage.CHANGENOTE, "Renamed from "+fromPage.getName() );
+        toPage.setAuthor( context.getCurrentUser().getName() );
+        
+        engine.getPageManager().putPageText( toPage, engine.getPureText( toPage ) );
+        
+        //
+        //  Update the references
+        //
+        
+        engine.getReferenceManager().pageRemoved( fromPage );
+        engine.updateReferences( toPage );
+
+        //
+        //  Update referrers first
+        //
+        if( changeReferrers )
+        {
+            updateReferrers( context, fromPage, toPage );
+        }
+
+
+        //
+        //  Done, return the new name.
+        //
+        return renameTo;
+    }
+
+    /**
+     *  This method finds all the pages which have anything to do with the fromPage and
+     *  change any referrers it can figure out in that page.
+     *  
+     *  @param context WikiContext in which we operate
+     *  @param fromPage The old page
+     *  @param toPage The new page
+     */
+    @SuppressWarnings("unchecked")
+    private void updateReferrers( WikiContext context, WikiPage fromPage, WikiPage toPage
)
+    {
+        WikiEngine engine = context.getEngine();
+        Set<String> referrers = new TreeSet<String>();
+        
+        Collection<String> r = engine.getReferenceManager().findReferrers( fromPage.getName()
);
+        if( r != null ) referrers.addAll( r );
+        
+        try
+        {
+            Collection<Attachment> attachments = engine.getAttachmentManager().listAttachments(
fromPage );
+
+            for( Attachment att : attachments  )
+            {
+                Collection<String> c = engine.getReferenceManager().findReferrers(att.getName());
+
+                if( c != null ) referrers.addAll(c);
+            }
+        }
+        catch( ProviderException e )
+        {
+            // We will continue despite this error
+            log.error( "Provider error while fetching attachments for rename", e );
+        }
+
+        
+        if( referrers.isEmpty() ) return; // No referrers
+        
+        for( String pageName : referrers )
+        {
+            WikiPage p = engine.getPage( pageName );
+            
+            String sourceText = engine.getPureText( p );
+            
+            String newText = replaceReferrerString( context, sourceText, fromPage.getName(),
toPage.getName() );
+            
+            if( m_camelCase )
+                newText = replaceCCReferrerString( context, newText, fromPage.getName(),
toPage.getName() );
+            
+            if( !sourceText.equals( newText ) )
+            {
+                p.setAttribute( WikiPage.CHANGENOTE, "Renaming change "+fromPage.getName()+"
to "+toPage.getName() );
+                p.setAuthor( context.getCurrentUser().getName() );
+         
+                try
+                {
+                    engine.getPageManager().putPageText( p, newText );
+                    engine.updateReferences( p );
+                }
+                catch( ProviderException e )
+                {
+                    //
+                    //  We fail with an error, but we will try to continue to rename
+                    //  other referrers as well.
+                    //
+                    log.error("Unable to perform rename.",e);
+                }
+            }
+        }
+    }
+
+    /**
+     *  Replaces camelcase links.
+     */
+    private String replaceCCReferrerString( WikiContext context, String sourceText, String
from, String to )
+    {
+        StringBuilder sb = new StringBuilder( sourceText.length()+32 );
+        
+        Pattern linkPattern = Pattern.compile( "\\p{Lu}+\\p{Ll}+\\p{Lu}+[\\p{L}\\p{Digit}]*"
);
+        
+        Matcher matcher = linkPattern.matcher( sourceText );
+        
+        int start = 0;
+        
+        while( matcher.find(start) )
+        {
+            String match = matcher.group();
+
+            sb.append( sourceText.substring( start, matcher.start() ) );
+
+            int lastOpenBrace = sourceText.lastIndexOf( '[', matcher.start() );
+            int lastCloseBrace = sourceText.lastIndexOf( ']', matcher.start() );
+            
+            if( match.equals( from ) && lastCloseBrace >= lastOpenBrace )
+            {
+                sb.append( to );
+            }
+            else
+            {
+                sb.append( match );
+            }
+            
+            start = matcher.end();
+        }
+        
+        sb.append( sourceText.substring( start ) );
+        
+        return sb.toString();
+    }
+
+    private String replaceReferrerString( WikiContext context, String sourceText, String
from, String to )
+    {
+        StringBuilder sb = new StringBuilder( sourceText.length()+32 );
+        
+        Pattern linkPattern = Pattern.compile( "([\\[\\~]?)\\[([^\\|\\]]*)(\\|)?([^\\|\\]]*)(\\|)?([^\\|\\]]*)\\]"
);
+        
+        Matcher matcher = linkPattern.matcher( sourceText );
+        
+        int start = 0;
+        
+        //System.out.println("====");
+        //System.out.println("SRC="+sourceText.trim());
+        while( matcher.find(start) )
+        {
+            char charBefore = (char)-1;
+            
+            if( matcher.start() > 0 ) 
+                charBefore = sourceText.charAt( matcher.start()-1 );
+            
+            if( matcher.group(1).length() > 0 || charBefore == '~' || charBefore == '['
) 
+            {
+                //
+                //  Found an escape character, so I am escaping.
+                //
+                sb.append( sourceText.substring( start, matcher.end() ) );
+                start = matcher.end();
+                continue;
+            }
+
+            String text = matcher.group(2);
+            String link = matcher.group(4);
+            String attr = matcher.group(6);
+             
+            /*
+            System.out.println("MATCH="+matcher.group(0));
+            System.out.println("   text="+text);
+            System.out.println("   link="+link);
+            System.out.println("   attr="+attr);
+             */
+            if( link.length() == 0 )
+            {
+                text = replaceSingleLink( context, text, from, to );
+            }
+            else
+            {
+                link = replaceSingleLink( context, link, from, to );
+                
+                //
+                //  A very simple substitution, but should work for quite a few cases.
+                //
+                text = TextUtil.replaceString( text, from, to );
+            }
+        
+            //
+            //  Construct the new string
+            //
+            sb.append( sourceText.substring( start, matcher.start() ) );
+            sb.append( "["+text );
+            if( link.length() > 0 ) sb.append( "|" + link );
+            if( attr.length() > 0 ) sb.append( "|" + attr );
+            sb.append( "]" );
+            
+            start = matcher.end();
+        }
+        
+        sb.append( sourceText.substring( start ) );
+        
+        return sb.toString();
+    }
+
+    /**
+     *  This method does a correct replacement of a single link, taking into
+     *  account anchors and attachments.
+     */
+    private String replaceSingleLink( WikiContext context, String original, String from,
String newlink )
+    {
+        int hash = original.indexOf( '#' );
+        int slash = original.indexOf( '/' );
+        String reallink = original;
+        
+        if( hash != -1 ) reallink = original.substring( 0, hash );
+        if( slash != -1 ) reallink = original.substring( 0,slash );
+        
+        reallink = MarkupParser.cleanLink( reallink );
+        
+        // WikiPage p  = context.getEngine().getPage( reallink );
+        // WikiPage p2 = context.getEngine().getPage( from );
+        
+        // System.out.println("   "+reallink+" :: "+ from);
+        // System.out.println("   "+p+" :: "+p2);
+        
+        //
+        //  Yes, these point to the same page.
+        //
+        if( reallink.equals(from) )
+        {
+            return newlink + ((hash > 0) ? original.substring( hash ) : "") + ((slash
> 0) ? original.substring( slash ) : "") ;
+        }
+        
+        return original;
+    }
+}

Added: incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/src/com/ecyrd/jspwiki/content/package.html
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/src/com/ecyrd/jspwiki/content/package.html?rev=682144&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/src/com/ecyrd/jspwiki/content/package.html
(added)
+++ incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/src/com/ecyrd/jspwiki/content/package.html
Sun Aug  3 05:17:34 2008
@@ -0,0 +1,13 @@
+<body>
+Provides content management functionality for JSPWiki.
+
+<h2>Package specification</h2>
+
+<p>This package will in 3.0 contain all content management functionality.  Currently
+it is a bit in-the-making.</p>
+
+<h2>Related documentation</h2>
+
+TBD.
+
+</body>
\ No newline at end of file



Mime
View raw message