[jboss-svn-commits] JBL Code SVN: r20759 - in labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss: labs and 1 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Wed Jun 25 08:16:29 EDT 2008
Author: szimano
Date: 2008-06-25 08:16:28 -0400 (Wed, 25 Jun 2008)
New Revision: 20759
Added:
labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/
labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/
labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/CSMigration.java
labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/CSMigrationStarter.java
labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/JSP2CSMarkupTranslator.java
labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/migration-howto.txt
labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/sql-script.txt
Log:
clearspace migration files
Added: labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/CSMigration.java
===================================================================
--- labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/CSMigration.java (rev 0)
+++ labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/CSMigration.java 2008-06-25 12:16:28 UTC (rev 20759)
@@ -0,0 +1,505 @@
+package org.jboss.labs.clearspace;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.activation.MimetypesFileTypeMap;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.ws.soap.SOAPFaultException;
+
+import org.jboss.wiki.WikiAttachment;
+import org.jboss.wiki.WikiEngine;
+import org.jboss.wiki.WikiPage;
+import org.jboss.wiki.configuration.ConfigurationParser;
+import org.w3c.dom.Text;
+
+import com.jivesoftware.base.UnauthorizedException;
+import com.jivesoftware.base.User;
+import com.jivesoftware.base.UserAlreadyExistsException;
+import com.jivesoftware.base.UserManager;
+import com.jivesoftware.base.UserNotFoundException;
+import com.jivesoftware.base.UserTemplate;
+import com.jivesoftware.base.wiki.WikiContentHelper;
+import com.jivesoftware.community.AttachmentException;
+import com.jivesoftware.community.AttachmentManager;
+import com.jivesoftware.community.Community;
+import com.jivesoftware.community.CommunityManager;
+import com.jivesoftware.community.CommunityNotFoundException;
+import com.jivesoftware.community.Document;
+import com.jivesoftware.community.DocumentAlreadyExistsException;
+import com.jivesoftware.community.DocumentManager;
+import com.jivesoftware.community.DocumentObjectNotFoundException;
+import com.jivesoftware.community.DocumentState;
+import com.jivesoftware.community.DocumentTypeManager;
+import com.jivesoftware.community.DuplicateIDException;
+import com.jivesoftware.community.JiveIterator;
+import com.jivesoftware.community.RejectedException;
+import com.jivesoftware.community.util.WikiUtils;
+
+public class CSMigration {
+
+ private static final String CS_HREF = "http://localhost:8080";
+ private static final String COMM_NAME = "JBossWiki";
+ private User unknownUser;
+ private Map<String, User> users;
+
+ private MimetypesFileTypeMap mimeTypes;
+
+ private UserManager userManager;
+ private DocumentManager documentManager;
+ private CommunityManager communityManager;
+ private DocumentTypeManager documentTypeManager;
+ private AttachmentManager attachmentManager;
+
+ private String dbCSUserName = "cs";
+ private String dbCSPass = "cs";
+ private String dbCSUrl = "jdbc:mysql://localhost:3306/cs";
+
+ private String dbNukesUserName = "portal";
+ private String dbNukesPass = "portalpassword";
+ private String dbNukesUrl = "jdbc:mysql://localhost:3306/nukes3";
+
+ private Map<String, String> pageDictionary;
+ private Map<String, String> pageDictionaryRev;
+ private Community jbossWikiCom;
+ private WikiEngine we;
+ private Set<String> pages;
+
+ private final static Map parameters = new HashMap();
+ private User adminUser;
+ private JSP2CSMarkupTranslator translator = new JSP2CSMarkupTranslator();
+ private FileWriter sqlScript;
+ private FileWriter log;
+
+ public CSMigration() {
+
+ }
+
+ private void init() throws CommunityNotFoundException,
+ UserNotFoundException {
+ we = new WikiEngine();
+ pages = we.getAllPageNames(ConfigurationParser.getDefaultLangugeCode());
+ pageDictionary = new HashMap<String, String>();
+ pageDictionaryRev = new HashMap<String, String>();
+ adminUser = userManager.getUser("admin");
+
+ JiveIterator<Community> communities = communityManager
+ .getCommunities(communityManager.getRootCommunity());
+
+ jbossWikiCom = null;
+ for (Community community : communities) {
+ if (community.getName().equals(COMM_NAME)) {
+ System.out.println("Found community: "
+ + community.getDisplayName());
+ communityManager.deleteCommunity(community);
+ System.out.println("Community deleted");
+ }
+ }
+
+ if (jbossWikiCom == null) {
+ jbossWikiCom = communityManager.createCommunity(communityManager
+ .getRootCommunity(), COMM_NAME, COMM_NAME,
+ "JBoss Wiki migration");
+ System.out.println("Community JBossWiki created");
+ }
+ mimeTypes = new MimetypesFileTypeMap(CSMigration.class
+ .getResourceAsStream("/org/jboss/wiki/fileaccess/mime.types"));
+
+ try {
+ unknownUser = userManager.getUser("unknown");
+ } catch (UserNotFoundException e) {
+ try {
+ UserTemplate ut = new UserTemplate("unknown");
+ ut.setPassword("Un4N0w&");
+ ut.setEmail("unknown at nowhere.org");
+
+ ut.setFederated(true);
+
+ userManager.createApplicationUser(ut);
+
+ System.out.println("User unknown added");
+
+ unknownUser = userManager.getUser("unknown");
+ } catch (UserAlreadyExistsException e1) {
+ // not going to happen
+ }
+ }
+
+ }
+
+ private void importAllPages(Set<String> toTransform) throws IOException {
+ // prepare dictionary
+ for (String pageName : toTransform) {
+ try {
+ Document wsd = documentManager.createDocument(adminUser,
+ documentTypeManager.getDefaultDocumentType(), null,
+ pageName, "");
+
+ WikiPage page = we.getByName(pageName, null, 1,
+ ConfigurationParser.getDefaultLangugeCode());
+
+ String content = translator.parse(page.getContent(),
+ pageDictionary, pageDictionaryRev);
+
+ org.w3c.dom.Document body = WikiContentHelper
+ .wikiToJiveDocument(content);
+
+ wsd.setBody(body);
+
+ wsd.setDocumentState(DocumentState.PUBLISHED);
+ wsd.save();
+
+ documentManager.addDocument(jbossWikiCom, wsd, parameters);
+
+ pageDictionary.put(pageName, wsd.getDocumentID());
+ pageDictionaryRev.put(wsd.getDocumentID(), pageName);
+ System.out.println("Added page: " + pageName + " as "
+ + wsd.getDocumentID());
+ } catch (DocumentAlreadyExistsException e) {
+ // ignore
+ e.printStackTrace();
+ } catch (SOAPFaultException e) {
+ e.printStackTrace();
+ System.out.println("Error while processing page: " + pageName);
+
+ } catch (DuplicateIDException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (RejectedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void importVersionsAndAttachments(Set<String> toTransform)
+ throws Exception {
+ // Connection c = getCSConnection();
+
+ byte[] bytes = new byte[1024 * 1024 * 100]; // 100 MB
+ try {
+ for (String pageName : toTransform) {
+
+ WikiPage page = we.getByName(pageName, null,
+ ConfigurationParser.getDefaultLangugeCode());
+
+ Document original = documentManager.getDocument(pageDictionary
+ .get(pageName));
+
+ // add attachments
+
+ Set<String> atts = we.getAttachmentsSet(page,
+ ConfigurationParser.getDefaultLangugeCode());
+
+ if (atts != null)
+ for (String att : atts) {
+ try {
+ WikiAttachment wa = we.getAttachment(
+ page.getName(), att, ConfigurationParser
+ .getDefaultLangugeCode());
+
+ attachmentManager.createAttachment(original, att,
+ mimeTypes.getContentType(att), wa
+ .getInputStream(), null);
+
+ wa.getInputStream().close();
+
+ System.out.println("Attachment " + att
+ + " added for " + page.getName());
+ } catch (AttachmentException e) {
+ System.err
+ .println("Problem with adding attachment "
+ + att + " for page " + pageName);
+ e.printStackTrace();
+ }
+ }
+
+ // add versions
+ for (int ver = 1; ver <= page.getLastVersion(); ver++) {
+ WikiPage pageVer = we.getByName(pageName, null, ver,
+ ConfigurationParser.getDefaultLangugeCode());
+
+ String content = translator.parse(pageVer.getContent(),
+ pageDictionary, pageDictionaryRev);
+
+ org.w3c.dom.Document body = WikiContentHelper
+ .wikiToJiveDocument(content);
+
+ original.setBody(body);
+ original.setCreationDate(pageVer.getEditDate());
+ original.setModificationDate(pageVer.getEditDate());
+
+ User user = getUser(pageVer.getLastAuthor().getName());
+
+ original.setUser(user);
+
+ // original.addAuthor(user);
+
+ original.save();
+
+ long creation = pageVer.getEditDate().getTime();
+
+ // update user and last modification date
+
+ String sql = "UPDATE jiveDocVersion j SET modificationDate='"
+ + creation
+ + "', userID='"
+ + user.getID()
+ + "' WHERE j.internalDocID='"
+ + original.getID()
+ + "' and j.versionID='" + (ver + 1) + "';";
+ // System.out.println("SQL: " + sql);
+
+ sqlScript.write(sql + "\n");
+
+ // c.createStatement().execute(sql);
+
+ original = documentManager.getDocument(original
+ .getDocumentID());
+
+ System.out.println("Version " + ver + " updated for "
+ + pageVer.getName());
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ /*
+ * if (c != null) { c.close(); }
+ */
+ }
+
+ }
+
+ /**
+ * @param args
+ * @throws Exception
+ * @throws DocumentAlreadyExistsException
+ */
+ public void migrate() throws Exception {
+
+ try {
+ Date start = new Date();
+
+ init();
+
+ Set<String> toTransform = new TreeSet<String>();
+
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm");
+
+ File fSqlScript = new File("versions_and_users-" + sdf.format(start)
+ + ".sql");
+
+ sqlScript = new FileWriter(fSqlScript);
+
+ log = new FileWriter(new File("log-" + sdf.format(start) + ".sql"));
+ for (String pageName : pages) {
+ if (pageName.matches("[JT].*")) {
+ toTransform.add(pageName);
+ }
+ }
+
+ importAllPages(toTransform);
+
+ importVersionsAndAttachments(toTransform);
+
+ Date end = new Date();
+
+ createMigrationInfoPage(start, end);
+
+ System.out
+ .println("Migration DONE ! Please stop clearspace and run script "
+ + fSqlScript.getAbsolutePath());
+ } finally {
+ sqlScript.close();
+ log.close();
+ }
+ }
+
+ private void createMigrationInfoPage(Date start, Date end)
+ throws DuplicateIDException, UnauthorizedException,
+ DocumentAlreadyExistsException, RejectedException {
+ // save dictionary
+ Properties p = new Properties();
+ p.putAll(pageDictionary);
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm");
+
+ try {
+ p.store(new FileOutputStream("pages-" + sdf.format(start)
+ + ".properties"), "migration from " + end.toString());
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ StringBuffer migration = new StringBuffer();
+
+ migration.append("h3. Migration from JSPWiki to Clearspace\n").append(
+ "Started on ").append(start.toString())
+ .append(" and ended on ").append(end.toString()).append(
+ " taking ").append(
+ (end.getTime() - start.getTime()) / 1000).append(
+ " seconds\n\n").append("h3. List of pages\n").append(
+ "||Original||Clearspace ID||\n");
+
+ for (String key : pageDictionary.keySet()) {
+ migration.append("|").append(key).append("|").append(
+ pageDictionary.get(key)).append("|\n");
+ }
+
+ migration.append("\n\n");
+
+ Document d = documentManager.createDocument(adminUser,
+ documentTypeManager.getDefaultDocumentType(), null,
+ "JSPWikiToClearspaceMigrationDetails", migration.toString());
+ d.setDocumentState(DocumentState.PUBLISHED);
+ d.setBody(WikiContentHelper.wikiToJiveDocument(migration.toString()));
+ d.save();
+
+ documentManager.addDocument(jbossWikiCom, d, parameters);
+
+ System.out.println("Page JSPWikiToClearspaceMigrationDetails added as "
+ + d.getDocumentID());
+
+ }
+
+ private User getUser(String userName) {
+ if (users == null) {
+ users = new HashMap<String, User>();
+ }
+
+ // maybe we know it already
+ if (users.containsKey(userName)) {
+ return users.get(userName);
+ }
+
+ User user = null;
+ Connection c = null;
+
+ // try to get from clearspace
+ try {
+ user = userManager.getUser(userName);
+ } catch (UserNotFoundException e) {
+ // there's no user - try to migrate it
+ try {
+ c = getNukesConnection();
+ ResultSet rs = c.createStatement().executeQuery(
+ "SELECT * FROM nuke_users WHERE pn_uname='" + userName
+ + "';");
+ if (rs.next()) {
+ LabsUser nukeUser = new LabsUser(rs);
+
+ try {
+ UserTemplate ut = new UserTemplate(userName);
+ ut.setFederated(true);
+
+ ut = mapDetails(ut, nukeUser);
+ userManager.createApplicationUser(ut);
+
+ user = userManager.getUser(userName);
+ users.put(userName, user);
+
+ return user;
+ } catch (Exception ex) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ } else {
+ users.put(userName, unknownUser);
+ return unknownUser;
+ }
+ } catch (SQLException e1) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (Exception e1) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ } finally {
+ if (c != null) {
+ try {
+ c.close();
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ users.put(userName, user);
+
+ return user;
+ }
+
+ private UserTemplate mapDetails(UserTemplate ut, LabsUser nukeUser) {
+ ut.setEmail(nukeUser.getEmail());
+ ut.setName(nukeUser.getName());
+ ut.setPasswordHash(nukeUser.getPasswordHash());
+
+ return ut;
+ }
+
+ private Connection getCSConnection() throws Exception {
+ Class.forName("com.mysql.jdbc.Driver").newInstance();
+ return DriverManager.getConnection(dbCSUrl, dbCSUserName, dbCSPass);
+ }
+
+ private Connection getNukesConnection() throws Exception {
+ Class.forName("com.mysql.jdbc.Driver").newInstance();
+ return DriverManager.getConnection(dbNukesUrl, dbNukesUserName,
+ dbNukesPass);
+ }
+
+ public void setUserManager(UserManager userManager) {
+ this.userManager = userManager;
+ checkIfCanStart();
+ }
+
+ public void setDocumentManager(DocumentManager documentManager) {
+ this.documentManager = documentManager;
+ checkIfCanStart();
+ }
+
+ public void setCommunityManager(CommunityManager communityManager) {
+ this.communityManager = communityManager;
+ checkIfCanStart();
+ }
+
+ public void setDocumentTypeManager(DocumentTypeManager documentTypeManager) {
+ this.documentTypeManager = documentTypeManager;
+ checkIfCanStart();
+ }
+
+ public void setAttachmentManager(AttachmentManager attachmentManager) {
+ this.attachmentManager = attachmentManager;
+ checkIfCanStart();
+ }
+
+ private void checkIfCanStart() {
+ /*
+ * if (userManager != null && documentManager != null &&
+ * communityManager != null && documentTypeManager != null &&
+ * attachmentManager != null) { System.out.println("\n\nMigration
+ * started"); try {
+ *
+ * migrate(); } catch (Exception e) { // TODO Auto-generated catch block
+ * e.printStackTrace(); } System.out.println("Migration finished\n\n"); }
+ */
+ }
+}
Added: labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/CSMigrationStarter.java
===================================================================
--- labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/CSMigrationStarter.java (rev 0)
+++ labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/CSMigrationStarter.java 2008-06-25 12:16:28 UTC (rev 20759)
@@ -0,0 +1,38 @@
+package org.jboss.labs.clearspace;
+
+import org.acegisecurity.Authentication;
+import org.acegisecurity.AuthenticationException;
+import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
+
+public class CSMigrationStarter implements
+ org.acegisecurity.providers.AuthenticationProvider {
+ private CSMigration migration;
+
+ public CSMigrationStarter() {
+
+ }
+
+ public void setMigration(CSMigration migration) {
+ this.migration = migration;
+ }
+
+ public Authentication authenticate(Authentication authentication)
+ throws AuthenticationException {
+
+ try {
+ if (System.getenv("MIGRATE") != null) {
+ migration.migrate();
+ }
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ public boolean supports(Class authentication) {
+ return authentication == UsernamePasswordAuthenticationToken.class;
+ }
+
+}
Added: labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/JSP2CSMarkupTranslator.java
===================================================================
--- labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/JSP2CSMarkupTranslator.java (rev 0)
+++ labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/JSP2CSMarkupTranslator.java 2008-06-25 12:16:28 UTC (rev 20759)
@@ -0,0 +1,1049 @@
+/**************************************************
+ * *
+ * JBoss Labs: Creating Professional Open Source *
+ * *
+ * Distributable under LGPL license. *
+ * See terms of license at gnu.org. *
+ * *
+ *************************************************/
+
+/*
+ Copyright (C) 2005 Damon Sicore,
+ Rali Genova,
+ Tomasz Szymanski,
+ Adam Warski,
+ JBoss, Inc.
+
+ This library 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 library 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 library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ */
+
+/**
+ * Portions of this work are based on the work
+ * of Janne Jalkanen of the JSPWiki project.
+ *
+ * Marked Portions are Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen at iki.fi)
+ *
+ * Those portions are marked by the 'author' javadoc tag
+ * and list Janne Jalkanen as the author of that method.
+ *
+ * This class is based on the JSPWiki 2.0 version
+ * of the TranslatorReader.java class. The original
+ * version of that class can be found here:
+ *
+ * http://anonsvn.labs.jboss.com/branches/forge/archives/jspwiki/src/com/ecyrd/jspwiki/TranslatorReader.java
+ *
+ */
+package org.jboss.labs.clearspace;
+
+/**
+ * @author <a href="mailto:rali.genova at jboss.org">Rali Genova </a>
+ * @author <a href="mailto:tomasz.szymanski at jboss.org">Tomasz Szymanski </a>
+ *
+ */
+import java.io.*;
+import java.util.regex.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.apache.log4j.Logger;
+import org.jboss.wiki.WikiCommon;
+import org.jboss.wiki.WikiPage;
+import org.jboss.wiki.WikiPlugin;
+import org.jboss.wiki.WikiSession;
+import org.jboss.wiki.configuration.ConfigurationParser;
+
+public class JSP2CSMarkupTranslator {
+
+ private Logger log;
+
+ private static String mediaPatterns;
+
+ /* formatting variables */
+
+ private boolean m_allowHTML = true;
+
+ private boolean m_isbold = false;
+
+ private boolean m_isitalic = false;
+
+ private boolean m_isTypedText = false;
+
+ private boolean m_istable = false;
+
+ private boolean m_isPre = false;
+
+ private boolean m_isdefinition = false;
+
+ private int m_listlevel = 0;
+
+ private int m_numlistlevel = 0;
+
+ private boolean m_camelCaseLinks = true; // camelCase enabled
+
+ /** Tag that gets closed at EOL. */
+ private String m_closeTag = null;
+
+ /** Allow this many characters to be pushed back in the stream. */
+ private static final int PUSHBACK_BUFFER_SIZE = 8;
+
+ /**
+ * These characters constitute word separators when trying to find CamelCase
+ * links.
+ */
+ private static final String WORD_SEPARATORS = ",.|:;+=&";
+
+ private PushbackReader m_in;
+
+ // stores the name of the wiki page we are currently processing
+ private String pageName = "";
+
+ private Map<String, String> linkDictRev;
+
+ private Map<String, String> linkDict;
+
+ public JSP2CSMarkupTranslator() {
+
+ }
+
+ /**
+ * Push back any character to the current input. Does not push back a read
+ * EOF, though.
+ *
+ * @author Janne Jalkanen
+ */
+ private void pushBack(int c) throws IOException {
+ if (c != -1) {
+ m_in.unread(c);
+ }
+ }
+
+ /**
+ * Wiki to HTML transformation method, plain URIs transformation not
+ * implemented
+ *
+ * @param page
+ * The String representation of a wiki page's content
+ * @return The final transformed into HTML string
+ * @author Janne Jalkanen
+ * @author Rali Genova
+ */
+ public String parseLinks(String page) throws IOException {
+ m_in = new PushbackReader(new StringReader(page), PUSHBACK_BUFFER_SIZE);
+ StringBuffer buf = new StringBuffer();
+ StringBuffer word = null;
+ int previousCh = -2;
+ int start = 0;
+ boolean quitReading = false;
+ boolean newLine = true; // FIXME: not true if reading starts in middle
+ // of buffer
+
+ while (!quitReading) {
+ int ch = nextToken();
+ String s = null;
+
+ // begin of HTML transformation
+ if (m_isPre) {
+ if (ch == '}') {
+ buf.append(handleClosebrace());
+ /*
+ * } else if (ch == '<') { buf.append("<"); } else if
+ * (ch == '>') { buf.append(">");
+ */
+ } else if (ch == -1) {
+ quitReading = true;
+ } else {
+ buf.append((char) ch);
+ }
+
+ continue;
+ }
+ /*
+ * CamelCase detection, a non-trivial endeavour. We keep track of
+ * all white-space separated entities, which we hereby refer to as
+ * "words". We then check for an existence of a CamelCase format
+ * text string inside the "word", and if one exists, we replace it
+ * with a proper link.
+ */
+
+ if (m_camelCaseLinks) {
+ // Quick parse of start of a word boundary.
+
+ if (word == null
+ && (Character.isWhitespace((char) previousCh)
+ || WORD_SEPARATORS.indexOf((char) previousCh) != -1 || newLine)
+ && !Character.isWhitespace((char) ch)) {
+ word = new StringBuffer();
+ }
+
+ // Are we currently tracking a word?
+ if (word != null) {
+ //
+ // Check for the end of the word.
+ //
+
+ // We don't want automatic link creation
+ /*
+ * if (Character.isWhitespace((char) ch) || ch == -1 ||
+ * WORD_SEPARATORS.indexOf((char) ch) != -1) { String
+ * potentialLink = word.toString();
+ *
+ * String camelCase = parseCamelCase(potentialLink);
+ *
+ * if (camelCase != null) { start =
+ * buf.toString().lastIndexOf(camelCase); buf.replace(start,
+ * start + camelCase.length(), handleHyperlinks(camelCase)); } //
+ * We've ended a word boundary, so time to reset. word =
+ * null; } else {
+ */
+ // This should only be appending letters and digits.
+ word.append((char) ch);
+ // } // if end of word
+ } // if word's not null
+
+ // Always set the previous character to test for word starts.
+ previousCh = ch;
+
+ } // if m_camelCaseLinks
+ //
+ // Check if any lists need closing down.
+ //
+
+ if (newLine && ch != '*' && ch != ' ' && m_listlevel > 0) {
+ buf.append("</LI>\n");
+ for (; m_listlevel > 0; m_listlevel--) {
+ buf.append("</UL>\n");
+ }
+ }
+
+ if (newLine && ch != '#' && ch != ' ' && m_numlistlevel > 0) {
+ buf.append("</LI>\n");
+ for (; m_numlistlevel > 0; m_numlistlevel--) {
+ buf.append("</OL>\n");
+ }
+ }
+
+ if (newLine && ch != '|' && m_istable) {
+ buf.append("</TABLE>\n");
+ m_istable = false;
+ m_closeTag = null;
+ }
+
+ switch (ch) {
+ case '\r':
+ // DOS linefeeds we forget
+ s = null;
+ break;
+
+ case '\n':
+ //
+ // Close things like headings, etc.
+ //
+ if (m_closeTag != null) {
+ buf.append(m_closeTag);
+ m_closeTag = null;
+ }
+
+ m_isdefinition = false;
+
+ if (newLine) {
+ // Paragraph change.
+
+ buf.append("\n");
+ } else {
+ buf.append("\n");
+ newLine = true;
+ }
+ /*
+ * wiki syntax handling, later to be refactored so multiple wiki
+ * syntax is supported
+ */
+
+ break;
+ case '\\':
+ s = handleBackslash();
+ break;
+
+ case '_':
+ s = handleUnderscore();
+ break;
+
+ case '\'':
+ s = handleApostrophe();
+ break;
+
+ case '{':
+ s = handleOpenbrace();
+ break;
+
+ case '}':
+ s = handleClosebrace();
+ break;
+
+ case '-':
+ s = handleDash();
+ break;
+
+ case '!':
+ if (newLine) {
+ s = handleHeading();
+ } else {
+ s = "!";
+ }
+ break;
+
+ case ';':
+ if (newLine) {
+ s = handleDefinitionList();
+ } else {
+ s = ";";
+ }
+ break;
+
+ case ':':
+ if (m_isdefinition) {
+ s = "}";
+ m_isdefinition = false;
+ } else {
+ s = ":";
+ }
+ break;
+
+ case '[':
+ s = handleOpenbracket();
+ break;
+
+ case '*':
+ if (newLine) {
+ int chn = nextToken();
+ buf.append("*");
+
+ if (chn != '*') {
+ buf.append(" ");
+ }
+
+ if (chn != ' ') {
+ pushBack(chn);
+ }
+ }
+ break;
+
+ case '#':
+ if (newLine) {
+ int chn = nextToken();
+ buf.append("#");
+
+ if (chn != '#') {
+ buf.append(" ");
+ }
+
+ if (chn != ' ') {
+ pushBack(chn);
+ }
+ }
+ break;
+
+ /*
+ * case '|': s = handleBar(newLine); break;
+ */
+
+ case '<':
+ s = m_allowHTML ? "<" : "<";
+ break;
+
+ case '>':
+ s = m_allowHTML ? ">" : ">";
+ break;
+
+ case '\"':
+ s = m_allowHTML ? "\"" : """;
+ break;
+
+ case '~':
+ s = handleTilde();
+ break;
+ case -1:
+ quitReading = true;
+ break;
+
+ default:
+ buf.append((char) ch);
+ newLine = false;
+ break;
+ }
+ if (s != null) {
+ buf.append(s);
+
+ newLine = false;
+ }
+
+ }
+
+ return buf.toString();
+ }
+
+ /**
+ * @param link -
+ * potential camel case link to be tested
+ * @return the string itself if not a camel case, and a proper link
+ * otherwise
+ * @author Rali Genova
+ * @author Janne Jalkanen
+ */
+ public static String parseCamelCase(String link) {
+ String camelCasepattern = "^([^\\p{Alnum}]*|\\~)([\\p{Upper}]+[\\p{Lower}]+[\\p{Upper}]+[\\p{Alnum}]*)[^\\p{Alnum}]*$";
+ Pattern camelCase = Pattern.compile(camelCasepattern);
+ Matcher camelMatch = camelCase.matcher(link);
+ if (camelMatch.matches()) {
+ String result = camelMatch.group(2); // get the camel case words
+ if (camelMatch.group(1) != null) {
+ if ((camelMatch.group(1).equals("~"))
+ || (camelMatch.group(1).indexOf('[') != -1)) {
+ return null; // this is camelCase escape or [...] link
+ }
+ }
+ return result;
+
+ }// if match
+ return null;
+ }
+
+ /* a collection of all media formats allowed on wiki */
+ private static Collection getImagePatterns() {
+ ArrayList patt = new ArrayList();
+ String imagepattern = mediaPatterns;
+ String[] elem = imagepattern.split(",");
+ for (int i = 0; i < elem.length; i++) {
+ patt.add(elem[i].trim());
+ }
+
+ return patt;
+ }
+
+ public static boolean checkImageLink(String text) {
+ ArrayList ptrns = (ArrayList) getImagePatterns();
+ for (int i = 0; i < ptrns.size(); i++) {
+ if (text.endsWith((String) ptrns.get(i))) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Generic escape of next character or entity.
+ */
+ private String handleTilde() throws IOException {
+ int ch = nextToken();
+
+ if (ch == '|')
+ return "|";
+
+ if (Character.isUpperCase((char) ch)) {
+ return String.valueOf((char) ch);
+ }
+
+ // No escape.
+ pushBack(ch);
+
+ return "~";
+ }
+
+ private String handleUnderscore() throws IOException {
+ int ch = nextToken();
+ String res = "_";
+
+ if (ch == '_') {
+ res = m_isbold ? "*" : "*";
+ m_isbold = !m_isbold;
+ } else {
+ pushBack(ch);
+ }
+
+ return res;
+ }
+
+ /**
+ * For example: italics.
+ */
+ private String handleApostrophe() throws IOException {
+ int ch = nextToken();
+ String res = "'";
+
+ if (ch == '\'') {
+ res = m_isitalic ? "+" : "+";
+ m_isitalic = !m_isitalic;
+ } else {
+ m_in.unread(ch);
+ }
+
+ return res;
+ }
+
+ private String handleDash() throws IOException {
+ int ch = nextToken();
+
+ if (ch == '-') {
+ int ch2 = nextToken();
+
+ if (ch2 == '-') {
+ int ch3 = nextToken();
+
+ if (ch3 == '-') {
+ // Empty away all the rest of the dashes.
+ // Do not forget to return the first non-match back.
+ while ((ch = nextToken()) == '-')
+ ;
+
+ pushBack(ch);
+ return "-----";
+ }
+
+ pushBack(ch3);
+ }
+ pushBack(ch2);
+ }
+
+ pushBack(ch);
+
+ return "-";
+ }
+
+ private String handleHeading() throws IOException {
+ StringBuffer buf = new StringBuffer();
+
+ int ch = nextToken();
+
+ if (ch == '!') {
+ int ch2 = nextToken();
+
+ if (ch2 == '!') {
+ buf.append("h2. ");
+ m_closeTag = "";
+ } else {
+ buf.append("h3. ");
+ m_closeTag = "";
+ pushBack(ch2);
+ }
+ } else {
+ buf.append("h4. ");
+ m_closeTag = "";
+ pushBack(ch);
+ }
+
+ return buf.toString();
+ }
+
+ // TODO handle list
+ private String handleUnorderedList() throws IOException {
+ StringBuffer buf = new StringBuffer();
+
+ if (m_listlevel > 0) {
+ buf.append("</LI>\n");
+ }
+
+ int numBullets = countChars(m_in, '*') + 1;
+
+ if (numBullets > m_listlevel) {
+ for (; m_listlevel < numBullets; m_listlevel++)
+ buf.append("<UL>\n");
+ } else if (numBullets < m_listlevel) {
+ for (; m_listlevel > numBullets; m_listlevel--)
+ buf.append("</UL>\n");
+ }
+
+ buf.append("<LI>");
+
+ return buf.toString();
+ }
+
+ // TODO handle list
+ private String handleOrderedList() throws IOException {
+ StringBuffer buf = new StringBuffer();
+
+ if (m_numlistlevel > 0) {
+ buf.append("</LI>\n");
+ }
+
+ int numBullets = countChars(m_in, '#') + 1;
+
+ if (numBullets > m_numlistlevel) {
+ for (; m_numlistlevel < numBullets; m_numlistlevel++)
+ buf.append("<OL>\n");
+ } else if (numBullets < m_numlistlevel) {
+ for (; m_numlistlevel > numBullets; m_numlistlevel--)
+ buf.append("</OL>\n");
+ }
+
+ buf.append("<LI>");
+
+ return buf.toString();
+
+ }
+
+ private int countChars(PushbackReader in, char c) throws IOException {
+ int count = 0;
+ int ch;
+
+ while ((ch = in.read()) != -1) {
+ if ((char) ch == c) {
+ count++;
+ } else {
+ in.unread(ch);
+ break;
+ }
+ }
+
+ return count;
+ }
+
+ private String handleBar(boolean newLine) throws IOException {
+ StringBuffer sb = new StringBuffer();
+
+ if (!m_istable && !newLine) {
+ return "|";
+ }
+
+ if (newLine) {
+ if (!m_istable) {
+ sb.append("<TABLE CLASS=\"wikitable\" BORDER=\"1\">\n");
+ m_istable = true;
+ }
+
+ sb.append("<TR>");
+ m_closeTag = "</TD></TR>";
+ }
+
+ int ch = nextToken();
+
+ if (ch == '|') {
+ if (!newLine) {
+ sb.append("</TH>");
+ }
+ sb.append("<TH>");
+ m_closeTag = "</TH></TR>";
+ } else {
+ if (!newLine) {
+ sb.append("</TD>");
+ }
+ sb.append("<TD>");
+ pushBack(ch);
+ }
+
+ return sb.toString();
+ }
+
+ private String handleDefinitionList() throws IOException {
+ if (!m_isdefinition) {
+ m_isdefinition = true;
+
+ m_closeTag = "{quote}";
+
+ return "{quote:title=";
+ }
+
+ return ";";
+ }
+
+ private String handleBackslash() throws IOException {
+ int ch = nextToken();
+
+ if (ch == '\\') {
+ int ch2 = nextToken();
+
+ if (ch2 == '\\') {
+ int ch3 = nextToken();
+
+ if (ch3 == '\\') {
+ // TODO handle backbackslash
+ // return "<p style='page-break-before: always' />";
+ }
+
+ pushBack(ch3);
+
+ //TODO page break for printer
+ return "\\";
+ }
+
+ pushBack(ch2);
+
+ return "\\";
+ }
+
+ pushBack(ch);
+
+ return "\\";
+ }
+
+ private String handleOpenbracket() throws IOException {
+ StringBuffer sb = new StringBuffer();
+ int ch;
+ boolean isPlugin = false;
+
+ while ((ch = nextToken()) == '[') {
+ sb.append((char) ch);
+ }
+
+ if (sb.length() > 0) {
+ return sb.toString();// not a link
+ }
+
+ //
+ // Find end of hyperlink
+ //
+ pushBack(ch);
+ ch = nextToken();
+
+ while (ch != -1) {
+ if (ch == ']')// && (!isPlugin || sb.charAt( sb.length()-1 ) ==
+ // '}'
+ // ) )
+ {
+ break;
+ }
+
+ sb.append((char) ch);
+
+ ch = nextToken();
+ }
+
+ if (ch == -1) {
+
+ return sb.toString();
+ }
+
+ return handleHyperlinks(sb.toString());
+ }
+
+ private String handleOpenbrace() throws IOException {
+ int ch = nextToken();
+ String res = "{";
+
+ if (ch == '{') {
+ int ch2 = nextToken();
+
+ if (ch2 == '{') {
+ res = "{code}";
+ m_isPre = true;
+ } else {
+ pushBack(ch2);
+ // TODO <TT> truetype
+ res = "{font:courier new}";
+ m_isTypedText = true;
+ }
+ } else {
+ pushBack(ch);
+ }
+
+ return res;
+ }
+
+ /**
+ * Handles both }} and }}}
+ */
+ private String handleClosebrace() throws IOException {
+ String res = "}";
+
+ int ch2 = nextToken();
+
+ if (ch2 == '}') {
+ int ch3 = nextToken();
+
+ if (ch3 == '}') {
+ if (m_isPre) {
+ m_isPre = false;
+ res = "{code}";
+ } else {
+ res = "}}}";
+ }
+ } else {
+ pushBack(ch3);
+ // TODO truetype
+ if (!m_isPre) {
+ res = "{font}";
+ m_isTypedText = false;
+ } else {
+ pushBack(ch2);
+ }
+ }
+ } else {
+ pushBack(ch2);
+ }
+
+ return res;
+ }
+
+ /**
+ * Returns true if the link is really command to insert a plugin.
+ * <P>
+ * Currently we just check if the link starts with "{INSERT", or just plain
+ * "{" but not "{$".
+ *
+ * @author Janne Jalkanen
+ *
+ * @param link
+ * Link text, i.e. the contents of text between [].
+ * @return True, if this link seems to be a command to insert a plugin here.
+ */
+ public static boolean isPluginLink(String link) {
+ return link.startsWith("{INSERT")
+ || (link.startsWith("{") && !link.startsWith("{$"));
+ }
+
+ /**
+ * method to create links for external pages of Wiki pages
+ *
+ * @param string
+ * @return the HTML link representation of the wiki page/external link
+ * @author Rali Genova
+ */
+ private String handleHyperlinks(String link) {
+ String result = "";
+ String text = "";
+ String wikiPage = "";
+
+ if (isPluginLink(link)) {
+ // return null; // we do not include plugin links for now
+ // TODO make those CS macros
+
+ return link;
+ }
+ int border = link.indexOf('|');
+ if (border != -1) // [text|link] case
+ {
+ text = link.substring(0, border);
+ link = link.substring(border + 1);
+
+ } else // [link] case
+ {
+ if (!isExternalLink(link)) {
+ text = cleanLink(link);
+ } else {
+ text = link;
+ }
+ }
+
+ /* can't be longer then 255 chars
+ if (text.length() > 255) {
+ System.out.println("Text longer !");
+ text = text.substring(0, 254);
+ }
+
+ if (link.length() > 255) {
+ System.out.println("Link longer !");
+ }*/
+
+ // external link
+ if (isExternalLink(link)) {
+ if (checkImageLink(link)) {
+ result = "!" + link + "!";// external
+ // image
+ } else
+ result = "[" + text + "|" + link + "]";
+ }
+ // internal link
+ else {
+ // check if a footnote
+ if (link.startsWith("#"))// footnote reference
+ {// TODO handle footnote def
+ // http://labs.jboss.com/JSPWiki/Wiki.jsp?page=TextFormattingRules#ref-TextFormattingRules-1
+ result = "{FOOTNOTE RED " + link + " " + text + "}";
+
+ } else if (isNumber(link))// defines footnote
+ {// TODO handle footnote ref
+ result = "{FOOTNOTE DEF " + link + " " + text + "}";
+ }
+
+ // check if not an image link as well
+ else if (checkImageLink(link)) {
+ result = "!" + link + "!";
+
+ }
+ // check for attachments later on //TODO hanle attachments
+ else {
+
+ /*
+ * wikiPage = wikiEngine.getRealName(cleanLink(link), wPage
+ * .getLangCode()); if (wikiEngine.pageExists(wikiPage,
+ * wPage.getLangCode())) { result = "<a href=\"" + portalHome +
+ * wikiHome + page + wikiPage + language + wPage.getLangCode() +
+ * "\">" + text + "</a>"; } else result = "<u>" + text + "</u>" + "<a
+ * href=\"" + portalHome + wikiHome + page + wikiPage + language +
+ * wPage.getLangCode() + "\">" + "?" + "</a>";
+ */
+ return "[" + text + "|" + linkDict.get(link) + "]";
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Figures out if a link is an off-site link. This recognizes the most
+ * common protocols by checking how it starts. (clears all white space in
+ * case the link starts with '\n' or [space]
+ *
+ * @author Janne Jalkanen
+ */
+ public static boolean isExternalLink(String link) {
+ link = link.trim();
+ return link.startsWith("http:") || link.startsWith("ftp:")
+ || link.startsWith("https:") || link.startsWith("mailto:")
+ || link.startsWith("news:") || link.startsWith("file:");
+ }
+
+ private int nextToken() throws IOException {
+ return m_in.read();
+ }
+
+ /**
+ * Push back any character to the current input. Does not push back a read
+ * EOF, though.
+ */
+
+ /**
+ * Cleans a Wiki name.
+ * <P>[ This is a link ] -> ThisIsALink
+ *
+ * @param link
+ * Link to be cleared. Null is safe, and causes this to return
+ * null.
+ * @return A cleaned link.
+ *
+ * @since 2.0
+ * @author Janne Jalkanen
+ */
+ public static String cleanLink(String link) {
+ StringBuffer clean = new StringBuffer();
+
+ if (link == null)
+ return null;
+
+ //
+ // Compress away all whitespace and capitalize
+ // all words in between.
+ //
+
+ StringTokenizer st = new StringTokenizer(link, " -");
+
+ while (st.hasMoreTokens()) {
+ StringBuffer component = new StringBuffer(st.nextToken());
+
+ component.setCharAt(0, Character.toUpperCase(component.charAt(0)));
+
+ //
+ // We must do this, because otherwise compiling on JDK 1.4 causes
+ // a downwards incompatibility to JDK 1.3.
+ //
+ clean.append(component.toString());
+ }
+
+ //
+ // Remove non-alphanumeric characters that should not
+ // be put inside WikiNames. Note that all valid
+ // Unicode letters are considered okay for WikiNames.
+ // It is the problem of the WikiPageProvider to take
+ // care of actually storing that information.
+ //
+
+ for (int i = 0; i < clean.length(); i++) {
+ if ((clean.charAt(i) != '/')
+ && !(Character.isLetterOrDigit(clean.charAt(i))
+ || clean.charAt(i) == '_' || clean.charAt(i) == '.')) {
+ clean.deleteCharAt(i);
+ --i; // We just shortened this buffer.
+ }
+ }
+
+ //
+ // Capitalise words in subpages
+ //
+
+ for (int i = 0; i < clean.length() - 1; i++) {
+ if ((clean.charAt(i) == '/')
+ && (Character.isLowerCase(clean.charAt(i + 1)))) {
+ clean.setCharAt(i + 1, Character.toUpperCase(clean
+ .charAt(i + 1)));
+ }
+ }
+
+ return clean.toString();
+ }
+
+ /**
+ * Returns true, if the argument contains a number, otherwise false. In a
+ * quick test this is roughly the same speed as Integer.parseInt() if the
+ * argument is a number, and roughly ten times the speed, if the argument is
+ * NOT a number.
+ */
+
+ public static boolean isNumber(String s) {
+ if (s == null)
+ return false;
+
+ if (s.length() > 1 && s.charAt(0) == '-')
+ s = s.substring(1);
+
+ for (int i = 0; i < s.length(); i++) {
+ if (!Character.isDigit(s.charAt(i)))
+ return false;
+ }
+
+ return true;
+ }
+
+ // not sure what it is supposed to do but neccessary to compile
+ public void next() {
+ }
+
+ public void initTranslator() {
+ m_allowHTML = true;
+ m_isbold = false;
+ m_isitalic = false;
+ m_isTypedText = false;
+ m_istable = false;
+ m_isPre = false;
+ m_isdefinition = false;
+ m_listlevel = 0;
+ m_numlistlevel = 0;
+ m_camelCaseLinks = true; // camelCase enabled
+ /** Tag that gets closed at EOL. */
+ m_closeTag = null;
+
+ mediaPatterns = ".png , .jpeg, .jpg , .gif , .bmp";
+ }
+
+ public String parse(String pageContent, Map<String, String> linkDict,
+ Map<String, String> linkDictRev) throws IOException {
+
+ this.linkDict = linkDict;
+ this.linkDictRev = linkDictRev;
+
+ initTranslator();
+
+ String replace = parseLinks(pageContent);
+
+ return replace;
+
+ }
+
+ protected boolean executePlugins() {
+ return true;
+ }
+
+}
Added: labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/migration-howto.txt
===================================================================
--- labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/migration-howto.txt (rev 0)
+++ labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/migration-howto.txt 2008-06-25 12:16:28 UTC (rev 20759)
@@ -0,0 +1,11 @@
+Clearspace Migration HOWTO
+
+1. Install clearspace
+2. create db with default charset utf default collate utf8_general_ci (//TODO)
+3. setup cs with db created
+4. run sql-script.txt (change db name if needed)
+ALTER TABLE `cs`.`jiveWikiLink` MODIFY COLUMN `targetText` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL;
+5. set envirnment MIGRATE to true export MIGRATE=true
+6. run clearspace, login -> migration will start
+7. Stop clearspace, run generated sql script in mysql (see clearspace log) versions_and_users-${DATE}.sql
+8. remove MIGRATE env from environment. start clearspace. check the migration
Added: labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/sql-script.txt
===================================================================
--- labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/sql-script.txt (rev 0)
+++ labs/jbosslabs/trunk/portal-extensions/jbosswiki/wiki-common/src/java/org/jboss/labs/clearspace/sql-script.txt 2008-06-25 12:16:28 UTC (rev 20759)
@@ -0,0 +1 @@
+ALTER TABLE `cs`.`jiveWikiLink` MODIFY COLUMN `targetText` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL;
More information about the jboss-svn-commits
mailing list