2 * Moxkiriya standalone Wiki.
5 * @author Ryuhei Terada
6 * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
9 package com.wiki.standalone.moxkiriya;
12 import java.io.FileInputStream;
13 import java.io.FileOutputStream;
14 import java.net.NetworkInterface;
15 import java.util.ArrayList;
16 import java.util.Enumeration;
17 import java.util.HashMap;
18 import java.util.Hashtable;
19 import java.util.Iterator;
21 import javax.jcr.Credentials;
22 import javax.jcr.ImportUUIDBehavior;
23 import javax.jcr.NamespaceException;
24 import javax.jcr.NamespaceRegistry;
25 import javax.jcr.Node;
26 import javax.jcr.NodeIterator;
27 import javax.jcr.Property;
28 import javax.jcr.Repository;
29 import javax.jcr.RepositoryException;
30 import javax.jcr.Session;
31 import javax.jcr.Value;
32 import javax.jcr.ValueFactory;
33 import javax.jcr.Workspace;
34 import javax.jcr.nodetype.NodeType;
35 import javax.jcr.query.Query;
36 import javax.jcr.query.QueryManager;
37 import javax.jcr.version.Version;
38 import javax.jcr.version.VersionHistory;
39 import javax.jcr.version.VersionIterator;
40 import javax.jcr.version.VersionManager;
41 import javax.naming.Context;
42 import javax.naming.InitialContext;
44 import org.apache.jackrabbit.core.jndi.RegistryHelper;
45 import org.apache.jackrabbit.value.StringValue;
47 import com.wiki.standalone.moxkiriya.PageData.FileData;
50 * WikiRepository class.
53 public class WikiRepository {
54 /** repository_cluster_derby.xml */
55 public static final String REPOSITORY_CUSTER_FILENAME = "repository_cluster_derby.xml";
57 /** repository_local.xml */
58 public static final String REPOSITORY_LOCAL_FILENAME = "repository_local.xml";
60 public static final String REOPSITORY_DIRNAME = "Repository";
62 /** Moxkiriya repository generic namespace */
63 public static final String NAMESPACE_MOXKI = "moxki";
65 public static final String NAMESPACE_MOXKI_URI = "https://osdn.net/users/ryuhei__terada/pf/Moxkiriya7/moxki/1.0";
67 /** Node name "wikiroot" */
68 public static final String NODE_WIKIROOT = NAMESPACE_MOXKI + ":wikiroot";
70 /** Node name "namespace" */
71 public static final String NODE_NAMESPACE = NAMESPACE_MOXKI + ":namespacelist";
73 /** Property name "namespace" */
74 public static final String PROPERTY_NAMESPACE = NAMESPACE_MOXKI + ":namespace";
76 /** Property value "Main" in namespace */
77 public static final String PROPERTY_MAIN = "Main";
79 /** Property value "Category" in namespace */
80 public static final String PROPERTY_CATEGORY = "Category";
82 /** Property value "File" in namespace */
83 public static final String PROPERTY_FILE = "File";
85 /** Node name "pages" */
86 public static final String NODE_PAGES = NAMESPACE_MOXKI + ":pages";
88 /** Node name "page" */
89 public static final String NODE_PAGE = NAMESPACE_MOXKI + ":page";
91 /** Property name "title" */
92 public static final String PROPERTY_TITLE = NAMESPACE_MOXKI + ":title";
94 /** Property name "content" */
95 public static final String PROPERTY_CONTENT = NAMESPACE_MOXKI + ":content";
97 /** Property name "category" */
98 public static final String PROPERTY_category = NAMESPACE_MOXKI + ":category";
100 /** Node name "file" */
101 public static final String NODE_FILE = NAMESPACE_MOXKI + ":file";
103 /** Repository Home directory */
104 private String repositoryHomeDir_;
106 /** repository.xml */
107 private String repositoryFile_;
109 /** Initial context settings table */
110 private static Hashtable<String, String> envHashTable = new Hashtable<String, String>() {
111 private static final long serialVersionUID = 1L;
113 put(Context.INITIAL_CONTEXT_FACTORY,
114 "org.apache.jackrabbit.core.jndi.provider.DummyInitialContextFactory");
117 put(Context.PROVIDER_URL, "localhost");
122 private Repository repository_;
125 private Session session_;
129 * @param wikirootPath
132 public WikiRepository(File wikirootPath) throws Exception {
133 SettingManager settingMgr = SettingManager.getInstance();
135 setSystemProperties();
137 String configXML = settingMgr.get(SettingManager.SETINGKEY_CLUSTER).equals("true")
138 ? REPOSITORY_CUSTER_FILENAME
139 : REPOSITORY_LOCAL_FILENAME;
141 repositoryHomeDir_ = settingMgr.getAbsolutePath(REOPSITORY_DIRNAME);
142 repositoryFile_ = settingMgr.getAbsolutePath(configXML);
144 InitialContext initialContext = new InitialContext(envHashTable);
145 RegistryHelper.registerRepository(initialContext,
150 repository_ = (Repository)initialContext.lookup("repo");
151 session_ = repository_.login((Credentials)null);
157 public void closeSession() {
162 * Build Apache Jackrabbit Repository.
166 public void buildWikiRepository(PageData pageData) throws Exception {
167 Workspace workspace = session_.getWorkspace();
170 NamespaceRegistry nsRegistry = workspace.getNamespaceRegistry();
172 nsRegistry.getPrefix(NAMESPACE_MOXKI_URI);
173 } catch(NamespaceException e) {
175 * Build Apache Jackrabbit Repository if namespace"moxki" hasnot registered.
177 workspace.getNamespaceRegistry().registerNamespace(NAMESPACE_MOXKI, NAMESPACE_MOXKI_URI);
179 Node root = session_.getRootNode();
180 Node wikiroot = root.addNode(NODE_WIKIROOT);
181 Node namespace = wikiroot.addNode(NODE_NAMESPACE);
182 namespace.setProperty(PROPERTY_NAMESPACE,
184 new StringValue(PROPERTY_MAIN),
185 new StringValue(PROPERTY_CATEGORY),
186 new StringValue(PROPERTY_FILE)
188 wikiroot.addNode(NODE_PAGES);
202 public Node addPageNode(PageData pageData) throws Exception {
203 Node root = session_.getRootNode();
204 Node wikiroot = root.getNode(NODE_WIKIROOT);
205 Node pagesNode = wikiroot.getNode(NODE_PAGES);
206 Node pageNode = pagesNode.addNode(NODE_PAGE);
208 pageNode.addMixin(NodeType.MIX_VERSIONABLE);
209 pageNode.addMixin(NodeType.MIX_REFERENCEABLE);
211 return transformPageDataToNode(pageData, pageNode);
215 * Transform PageData to node.
221 public Node transformPageDataToNode(PageData pageData, Node node) throws Exception {
222 node.setProperty(PROPERTY_NAMESPACE, new StringValue(pageData.getNamespace()));
223 node.setProperty(PROPERTY_TITLE, new StringValue(pageData.getTitle()));
224 node.setProperty(PROPERTY_CONTENT, new StringValue(pageData.getContent()));
226 ArrayList<String> categories = pageData.getCategories();
227 Value[] values = new Value[] { new StringValue("") };
228 if(categories.size() > 0) {
229 values = new Value[categories.size()];
230 for(int count = 0; count < categories.size(); count++) {
231 values[count] = new StringValue(categories.get(count));
234 node.setProperty(PROPERTY_category, values);
236 FileData fileData = pageData.getFileData();
238 if(fileData != null) {
240 if(node.hasNode(WikiRepository.NODE_FILE) == true) {
241 fileNode = node.getNode(WikiRepository.NODE_FILE);
244 fileNode = node.addNode(WikiRepository.NODE_FILE, NodeType.NT_FILE);
245 fileNode.addNode(Property.JCR_CONTENT, NodeType.NT_RESOURCE);
248 Node nodeResource = fileNode.getNode(Property.JCR_CONTENT);
249 ValueFactory valueFactory = session_.getValueFactory();
251 nodeResource.setProperty(Property.JCR_DATA, valueFactory.createBinary(fileData.getInputStream()));
252 nodeResource.setProperty(Property.JCR_MIMETYPE, new StringValue(fileData.getMimeType()));
253 nodeResource.setProperty(Property.JCR_LAST_MODIFIED, valueFactory.createValue(fileData.getLastModified()));
254 if(fileData.getMimeType().startsWith("text/") == true) {
255 nodeResource.setProperty(Property.JCR_ENCODING, new StringValue("UTF-8"));
265 * @return HashMap<String, PageData>
268 private HashMap<String, PageData> executeQuery(String sql) throws Exception {
269 Workspace workspace = session_.getWorkspace();
270 QueryManager queryMgr = workspace.getQueryManager();
271 Query query = queryMgr.createQuery(sql, Query.JCR_SQL2);
272 NodeIterator iter = query.execute().getNodes();
274 return convertNodeIteratorToPageDataMap(iter);
278 * Get node matched namespace.
280 * @return HashMap<String, PageData>
283 public HashMap<String, PageData> queryPageNamespace(String namespace) throws Exception {
286 + " FROM [nt:unstructured]"
288 + " ISDESCENDANTNODE(["
289 + "/" + NODE_WIKIROOT + "/" + NODE_PAGES + "])"
291 + " [" + PROPERTY_NAMESPACE + "] = '" + namespace + "'"
296 * Get node matched uuid.
298 * @return HashMap<String, PageData>
301 public HashMap<String, PageData> queryPageUUID(String uuid) throws Exception {
304 + " FROM [nt:unstructured]"
306 + " ISDESCENDANTNODE(["
307 + "/" + NODE_WIKIROOT + "/" + NODE_PAGES + "])"
309 + " [" + Property.JCR_UUID + "] = '" + uuid + "'"
314 * Get node matched page title.
316 * @return HashMap<String, PageData>
319 public HashMap<String, PageData> queryPageTitle(String pageTitle) throws Exception {
320 String namespace = PROPERTY_MAIN;
321 String title = pageTitle;
323 if(pageTitle.contains(":") == true) {
324 namespace = pageTitle.substring(0, pageTitle.indexOf(":"));
325 title = pageTitle.substring(pageTitle.indexOf(":") + ":".length());
328 return queryPageTitle(title, namespace);
332 * Get node matched page title.
335 * @return HashMap<String, PageData>
338 public HashMap<String, PageData> queryPageTitle(String pageTitle, String namespace) throws Exception {
341 + " FROM [nt:unstructured]"
343 + " ISDESCENDANTNODE(["
344 + "/" + NODE_WIKIROOT + "/" + NODE_PAGES + "])"
346 + " [" + PROPERTY_NAMESPACE + "] = '" + namespace + "'"
348 + " [" + PROPERTY_TITLE + "] = '" + pageTitle + "'"
353 * Execute full text search.
358 public HashMap<String, PageData> queryPageFullTextSearch(String searchKey) throws Exception {
361 + " FROM [nt:unstructured]"
363 + " ISDESCENDANTNODE(["
364 + "/" + NODE_WIKIROOT + "/" + NODE_PAGES + "])"
366 + " CONTAINS([" + PROPERTY_TITLE + "], '" + searchKey + "')"
368 + " CONTAINS([" + PROPERTY_CONTENT + "], '" + searchKey + "')"
373 * Converter NodeIterator to PageDatMap.
375 * @return HashMap<String, PageData>
378 public HashMap<String, PageData> convertNodeIteratorToPageDataMap(NodeIterator nodeIter) throws Exception {
379 HashMap<String, PageData> pageDataMap = new HashMap<String, PageData>();
380 while(nodeIter.hasNext() == true) {
381 Node node = nodeIter.nextNode();
382 Version baseVersion = getBaseVersion(node);
383 PageData pageData = new PageData(node);
385 pageData.setBaseVersion(baseVersion);
386 pageDataMap.put(node.getProperty(Property.JCR_UUID).getString(), pageData);
393 * NamespaceList getter
397 public Value[] getNamespaceList() throws Exception {
398 Node namespace = session_.getNode("/" + NODE_WIKIROOT + "/" + NODE_NAMESPACE);
400 return namespace.getProperty(PROPERTY_NAMESPACE).getValues();
408 public void checkout(PageData pageData) throws Exception {
409 Node node = pageData.getNode();
411 session_.refresh(false);
413 Workspace workspace = session_.getWorkspace();
414 VersionManager versionMgr = workspace.getVersionManager();
415 versionMgr.checkout(node.getPath());
424 public PageData checkin(PageData pageData) throws Exception {
425 Workspace workspace = session_.getWorkspace();
426 VersionManager versionMgr = workspace.getVersionManager();
427 Node node = pageData.getNode();
430 node = addPageNode(pageData);
432 versionMgr.checkout(node.getPath());
435 String uuid = node.getProperty(Property.JCR_UUID).getString();
437 node = transformPageDataToNode(pageData, session_.getNodeByIdentifier(uuid));
441 versionMgr.checkin(node.getPath());
442 createCategoryPages(node);
444 String uuid = node.getProperty(Property.JCR_UUID).getString();
446 return new PageData(session_.getNodeByIdentifier(uuid));
454 public void cancelCheckout(PageData pageData) throws Exception {
455 Node node = pageData.getNode();
457 Workspace workspace = session_.getWorkspace();
458 VersionManager versionMgr = workspace.getVersionManager();
459 String path = node.getPath();
460 if(versionMgr.isCheckedOut(path) == true) {
461 versionMgr.restore(versionMgr.getBaseVersion(path), true);
471 public void deletePage(PageData pageData) throws Exception {
472 pageData.getNode().remove();
478 * @throws RepositoryException
480 public void refreshSession() throws RepositoryException {
481 session_.refresh(false);
485 * Set SystemProperties.
488 private void setSystemProperties() throws Exception {
489 SettingManager settingMgr = SettingManager.getInstance();
491 String macAddress = getMacAddress();
492 String username = System.getProperty("user.name");
493 String approot = settingMgr.get(SettingManager.SETTINGSKEY_WIKIROOT);
494 String partyName = settingMgr.getSelectedParty();
496 System.setProperty("cluster.id", String.valueOf(macAddress.hashCode()
499 System.setProperty("wiki.root", approot);
501 if(settingMgr.get(SettingManager.SETINGKEY_CLUSTER).equals("true")) {
502 System.setProperty("party.name", partyName);
503 System.setProperty("cluster.setting", "TRUE");
504 System.setProperty("dbserver.url", settingMgr.get(SettingManager.SETINGKEY_DBSERVER_URL));
505 System.setProperty("dbserver.port", settingMgr.get(SettingManager.SETINGKEY_DBSERVER_PORT));
506 System.setProperty("jdbc.driver", settingMgr.get(SettingManager.SETINGKEY_JDBC_DRIVER));
509 System.setProperty("cluster.setting", "FALSE");
510 System.setProperty("dbserver.url", "");
511 System.setProperty("dbserver.port", "");
512 System.setProperty("jdbc.driver", "");
517 * Mac Address getter.
521 private String getMacAddress() throws Exception {
522 StringBuffer buf = new StringBuffer();
523 Enumeration<NetworkInterface> nicList = NetworkInterface.getNetworkInterfaces();
525 while(nicList.hasMoreElements() == true) {
526 NetworkInterface nic = nicList.nextElement();
527 if(nic.getName().equals("lo") != true) {
528 byte[] macAddress = nic.getHardwareAddress();
529 if(macAddress != null) {
530 for(byte b: macAddress) {
531 buf.append(String.format("%02X-", b));
538 return buf.toString();
546 private void createCategoryPages(Node node) throws Exception {
547 Workspace workspace = session_.getWorkspace();
548 VersionManager versionMgr = workspace.getVersionManager();
549 Value[] categories = node.getProperty(PROPERTY_category).getValues();
551 for(Value category: categories) {
552 String title = category.getString();
554 if(title.isEmpty() != true) {
555 HashMap<String, PageData> map = queryPageTitle(title, PROPERTY_CATEGORY);
557 if(map.size() == 0) {
559 * category pageが未作成の場合、
561 PageData pageData = new PageData();
562 pageData.setNamespace(PROPERTY_CATEGORY);
563 pageData.setTitle(title);
565 Node categoryNode = addPageNode(pageData);
567 versionMgr.checkout(categoryNode.getPath());
568 versionMgr.checkin(categoryNode.getPath());
575 * Test namespace is contains namespaceList.
580 public boolean isContainsNamespaceList(String namespace) throws Exception {
581 Node root = session_.getRootNode();
582 Node wikiroot = root.getNode(NODE_WIKIROOT);
583 Node namespaceNode = wikiroot.getNode(NODE_NAMESPACE);
585 Value[] list = namespaceNode.getProperty(PROPERTY_NAMESPACE).getValues();
586 boolean isContains = false;
588 for(Value entry: list) {
589 if(entry.getString().equals(namespace) == true) {
599 * Version history getter.
601 * @return VersionIterator
604 public VersionIterator getVersionHistory(String uuid) throws Exception {
605 HashMap<String, PageData> nodeMap = queryPageUUID(uuid);
606 PageData pageData = nodeMap.values().iterator().next();
607 Node node = pageData.getNode();
609 Workspace workspace = session_.getWorkspace();
610 VersionManager versionMgr = workspace.getVersionManager();
611 VersionHistory versionHistory = versionMgr.getVersionHistory(node.getPath());
613 return versionHistory.getAllVersions();
617 * Base version getter.
622 public Version getBaseVersion(Node node) throws Exception {
623 Workspace workspace = session_.getWorkspace();
624 VersionManager versionMgr = workspace.getVersionManager();
626 return versionMgr.getBaseVersion(node.getPath());
635 public void restoreVersion(Version version, Node node) throws Exception {
636 Workspace workspace = session_.getWorkspace();
637 VersionManager versionMgr = workspace.getVersionManager();
639 versionMgr.restore(version, true);
643 * Import system view.
647 public void importSystemView(File outputFile) throws Exception {
648 FileInputStream inStream = new FileInputStream(outputFile);
651 Node root = session_.getRootNode();
652 Node wikiroot = root.getNode(NODE_WIKIROOT);
653 Node pagesNode = wikiroot.getNode(NODE_PAGES);
655 session_.importXML(pagesNode.getPath(), inStream, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
658 Node namespaceNode = wikiroot.getNode(NODE_NAMESPACE);
659 Value[] namespaces = namespaceNode.getProperty(PROPERTY_NAMESPACE).getValues();
661 for(Value namespace: namespaces) {
662 HashMap<String,PageData> map = queryPageNamespace(namespace.getString());
663 Iterator<PageData> iter = map.values().iterator();
664 while(iter.hasNext() == true) {
665 PageData pageData = iter.next();
676 * Export system view.
680 public void exportSystemView(File outputFile) throws Exception {
681 FileOutputStream outStream = new FileOutputStream(outputFile);
684 Node root = session_.getRootNode();
685 Node wikiroot = root.getNode(NODE_WIKIROOT);
686 Node pagesNode = wikiroot.getNode(NODE_PAGES);
688 session_.exportSystemView(pagesNode.getPath(), outStream, false, false);