svn commit: r541504 [2/7] - in /xml/xindice/trunk: ./ config/ java/scratchpad/webadmin/ java/src/org/apache/xindice/client/xmldb/embed/ java/src/org/apache/xindice/core/ java/src/org/apache/xindice/core/data/ java/src/org/apache/xindice/core/filer/ jav...

[email protected]
Newsgroups gmane.text.xml.xindice.devel
Message-ID <[email protected]>
Modified: xml/xindice/trunk/java/src/org/apache/xindice/util/StringUtilities.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/util/StringUtilities.java?view=diff&rev=541504&r1=541503&r2=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/util/StringUtilities.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/util/StringUtilities.java Thu May 24 18:43:39 2007
@@ -73,7 +73,7 @@
         for (int i = sb.length(); i < width; i++) {
             sb.append(' ');
         }
-        
+
         if (sb.length() > width) {
             sb.setLength(width);
         }
@@ -94,7 +94,7 @@
         for (int i = sb.length(); i < width; i++) {
             sb.insert(0, ' ');
         }
-        
+
         if (sb.length() > width) {
             return sb.toString().substring(sb.length() - width);
         } else {
@@ -162,7 +162,7 @@
     public static int findWhiteSpace(String value, int start) {
         char[] chars = value.toCharArray();
         for (int i = start; i < chars.length; i++) {
-            if (chars[i] <= 32) {
+            if (Character.isWhitespace(chars[i])) {
                 return i;
             }
         }
@@ -192,9 +192,8 @@
     public static String javaEncode(String value) {
         StringTokenizer st = new StringTokenizer(value, "\b\t\n\f\r\"\'\\", true);
         StringBuffer sb = new StringBuffer(value.length());
-        String token;
         while (st.hasMoreTokens()) {
-            token = st.nextToken();
+            String token = st.nextToken();
             if (token.equals("\b")) {
                 sb.append("\\b");
             } else if (token.equals("\t")) {
@@ -224,5 +223,69 @@
         } else {
             return s1.equals(s2);
         }
+    }
+
+    /**
+     * Converts input text into its XML representation by escaping all special symbols,
+     * if any are present.
+     *
+     * @param text Input string
+     * @return String with all the special symbols escaped 
+     */
+    public static String escapeXml(String text) {
+        char[] value = text.toCharArray();
+        StringBuffer buf = new StringBuffer();
+        int start = 0;
+        int len = 0;
+
+        for (int i = 0; i < value.length; i++) {
+            String outval = null;
+
+            switch (value[i]) {
+                case '&':
+                    outval = "&amp;";
+                    break;
+                case '\'':
+                    outval = "&apos;";
+                    break;
+                case '\"':
+                    outval = "&quot;";
+                    break;
+                case '<':
+                    outval = "&lt;";
+                    break;
+                case '>':
+                    outval = "&gt;";
+                    break;
+                default :
+                    len++;
+                    break;
+            }
+
+            if (outval != null) {
+                if (len > 0) {
+                    buf.append(value, start, len);
+                }
+                buf.append(outval);
+                start = i + 1;
+                len = 0;
+            }
+        }
+
+        if (len > 0) {
+            buf.append(value, start, len);
+        }
+
+        return buf.toString();
+    }
+
+    public static boolean isBlank(String str) {
+        for (int i = 0; i < str.length(); i++) {
+            if (!Character.isWhitespace(str.charAt(i))) {
+                return false;
+            }
+        }
+
+        return true;
     }
 }

Added: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/Location.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/Location.java?view=auto&rev=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/Location.java (added)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/Location.java Thu May 24 18:43:39 2007
@@ -0,0 +1,126 @@
+/*
+ * 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 org.apache.xindice.webadmin;
+
+import org.apache.xindice.core.Collection;
+import org.apache.xindice.core.DBException;
+import org.apache.xindice.core.Database;
+
+/**
+ * Helper class for parsing path information to get database, collection
+ * and resource name.
+ */
+public class Location {
+    private Collection collection;
+    private String name;
+    private boolean isRoot;
+
+    /**
+     * Create Location instance out of path information. There are several
+     * possible outcomes: <ul>
+     * <li>Path is empty or "/" - both collection and name are null, isRoot
+     * equals true;
+     * <li>Path matches some collection's canonical name - collection is
+     * set to that collection, name is null, isRoot equals false;
+     * <li>Path matches some document's canonical name - collection is set
+     * to the document's collection, name is document name, isRoot equals
+     * false;
+     * <li>Path could not be recognized, no database/collection match found -
+     * both collection and name are null, isRoot equals false
+     * </ul>
+     * In case there are collection and document that have the same name,
+     * collection has a precedence over the document.
+     * For example, if path is /db/col1/test, and collection col1 contains
+     * child collection test and a document test, collection test will be
+     * returned, not a document.
+     *
+     * @param path Path string
+     * @throws DBException
+     */
+    public Location(String path) throws DBException {
+        if (path == null || path.length() == 0 || path.equals("/")) {
+            isRoot = true;
+            return;
+        }
+
+        Database db = getDatabase(path);
+        if (db == null) {
+            collection = null;
+            name = null;
+            return;
+        }
+
+        StringBuffer buf = new StringBuffer(path);
+
+        // strip database name
+        String dbName = db.getName();
+        buf.delete(0, dbName.length() + 1);
+
+        Collection col;
+        if (buf.length() == 0 || (buf.length() == 1 && buf.charAt(0) == '/')) {
+            col = db;
+        } else {
+            col = db.getCollection(buf.toString());
+        }
+
+        String resourceName = null;
+        if (col == null) { // no collection found -> try resource
+            if (buf.charAt(buf.length() - 1) ==  '/') {
+                buf.deleteCharAt(buf.length() - 1);
+            }
+
+            int split = buf.lastIndexOf("/");
+            resourceName = buf.substring(split + 1, buf.length());
+            String colPath = buf.substring(0, split);
+
+            if (colPath.length() > 0) {
+                col = db.getCollection(colPath);
+            } else {
+                col = db;
+            }
+        }
+
+        collection = col;
+        if (collection != null) {
+            this.name = resourceName;
+        }
+    }
+
+    private Database getDatabase(String path) {
+        if (path.charAt(0) != '/') {
+            return null;
+        }
+
+        int end = path.indexOf('/', 1);
+        String dbName = (end != -1) ? path.substring(1, end) : path.substring(1);
+
+        return Database.getDatabase(dbName);
+    }
+
+    public Collection getCollection() {
+        return collection;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public boolean isRoot() {
+        return isRoot;
+    }
+}

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/Location.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/Location.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision Author Date

Added: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/PartialResponse.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/PartialResponse.java?view=auto&rev=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/PartialResponse.java (added)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/PartialResponse.java Thu May 24 18:43:39 2007
@@ -0,0 +1,150 @@
+/*
+ * 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 org.apache.xindice.webadmin;
+
+import org.apache.xindice.util.StringUtilities;
+
+import java.util.ArrayList;
+
+/**
+ * PartialResponse represents response part of the multi-status response
+ * document. Every partial response has its correspondent URL information
+ * (href element) and one or more elements with additional request-specific
+ * information.
+ */
+public class PartialResponse {
+    private final String href;
+    private ArrayList children;
+
+    public PartialResponse(String href) {
+        this.href = href;
+    }
+
+    public String getHref() {
+        return href;
+    }
+
+    /**
+     * Adds another element to the list of children of this partial response.
+     *
+     * @param name Element name
+     * @param value Element value
+     */
+    public void addContent(String name, String value) {
+        Content child = new Content(name);
+        child.setValue(value);
+        addContent(child);
+    }
+
+    /**
+     * Adds another element to the list of children of this partial response.
+     *
+     * @param child Existing element
+     */
+    public void addContent(Content child) {
+        if (children == null) {
+            children = new ArrayList();
+        }
+        children.add(child);
+    }
+
+    /**
+     * Builds XML out of partial response object.
+     *
+     * @return XML string
+     */
+    public String toString() {
+        StringBuffer buf = new StringBuffer(1024);
+        buf.append("<response>");
+        buf.append("<href>").append(StringUtilities.escapeXml(href)).append("</href>");
+
+        if (children != null && children.size() != 0) {
+            for (int i = 0; i < children.size(); i++) {
+                buf.append(((Content) children.get(i)).getContent());
+            }
+        }
+
+        buf.append("</response>");
+
+        return buf.toString();
+    }
+
+    /**
+     * Content class holds request-specific information in a tree-like
+     * structure. Every element of this tree can either be empty, have a
+     * text value or hold children elements.
+     */
+    public static class Content {
+        private ArrayList children;
+        private String name;
+        private String value;
+
+        public Content(String name) {
+            this.name = name;
+        }
+
+        public Content(String name, String value) {
+            this.name = name;
+            this.value = value;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+
+        public Content addChild(String name) {
+            Content child = new Content(name);
+            addChild(child);
+            return child;
+        }
+
+        public Content addChild(String name, String value) {
+            Content child = addChild(name);
+            child.setValue(value);
+            return child;
+        }
+
+        public void addChild(Content child) {
+            if (children == null) {
+                children = new ArrayList();
+            }
+            children.add(child);
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        private StringBuffer getContent() {
+            StringBuffer buf = new StringBuffer(1024);
+
+            buf.append("<").append(name).append(">");
+            if (value != null) {
+                buf.append(StringUtilities.escapeXml(value));
+            } else if (children != null && children.size() != 0) {
+                for (int i = 0; i < children.size(); i++) {
+                    buf.append(((Content) children.get(i)).getContent());
+                }
+            }
+
+            buf.append("</").append(name).append(">");
+
+            return buf;
+        }
+    }
+}

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/PartialResponse.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/PartialResponse.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision Author Date

Added: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/WebAdminManager.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/WebAdminManager.java?view=auto&rev=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/WebAdminManager.java (added)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/WebAdminManager.java Thu May 24 18:43:39 2007
@@ -0,0 +1,206 @@
+/*
+ * 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 org.apache.xindice.webadmin;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.apache.xindice.webadmin.webdav.components.DAVComponent;
+import org.apache.xindice.webadmin.viewer.HtmlCollectionViewer;
+import org.apache.xindice.webadmin.viewer.HtmlResourceViewer;
+import org.apache.xindice.webadmin.viewer.HtmlDatabaseViewer;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.HashMap;
+import java.util.ArrayList;
+
+/**
+ * Manager class that is responsible for reading configuration, initializing
+ * all components, and dispatching calls.
+ *
+ * WebAdminManager configuration has several sections descibing different
+ * components:
+ * <ul>
+ * <li>methods - list of supported WebDAV methods
+ * <li>colviewers - list of collection-level operations for WebAdmin
+ * <li>resviewers - list of resource-level operations for WebAdmin
+ * <li>dbviewers - list of database-level operations for WebAdmin
+ * </ul>
+ */
+public class WebAdminManager {
+
+    private static final HashMap methods = new HashMap();
+    private static final HashMap colViewers = new HashMap();
+    private static final HashMap resViewers = new HashMap();
+    private static final HashMap dbViewers = new HashMap();
+
+    private static String[] methodsList;
+    private static String[] colViewersList;
+    private static String[] resViewersList;
+    private static String[] dbViewersList;
+
+    private static final Log log = LogFactory.getLog(WebAdminManager.class);
+
+    public WebAdminManager(Document config) {
+        Node node = config.getElementsByTagName("methods").item(0);
+        try {
+            methodsList = processSection(node, "method", methods);
+        } catch (Exception e) {
+            log.error("Failed to load WebDAV methods", e);
+        }
+
+        node = config.getElementsByTagName("colviewers").item(0);
+        try {
+            colViewersList = processSection(node, "viewer", colViewers);
+        } catch (Exception e) {
+            log.error("Failed to load collection viewers", e);
+        }
+
+        node = config.getElementsByTagName("resviewers").item(0);
+        try {
+            resViewersList = processSection(node, "viewer", resViewers);
+        } catch (Exception e) {
+            log.error("Failed to load resource viewers", e);
+        }
+
+        node = config.getElementsByTagName("dbviewers").item(0);
+        try {
+            dbViewersList = processSection(node, "viewer", dbViewers);
+        } catch (Exception e) {
+            log.error("Failed to load DB viewers", e);
+        }
+    }
+
+    private String[] processSection(Node node, String name, HashMap storage) throws Exception {
+        NodeList nodes = node.getChildNodes();
+        ArrayList list = new ArrayList();
+        for (int i = 0; i < nodes.getLength(); i++) {
+
+            Node child = nodes.item(i);
+            if (child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals(name)) {
+                NamedNodeMap attrs = child.getAttributes();
+
+                String className = attrs.getNamedItem("class").getNodeValue();
+                Object object = Class.forName(className).newInstance();
+
+                String id = attrs.getNamedItem("id").getNodeValue();
+                if (id != null && id.length() > 0) {
+                    storage.put(id, object);
+                    list.add(id);
+
+                    Node attr = attrs.getNamedItem("default");
+                    if (attr != null && "true".equals(attr.getNodeValue())) {
+                        storage.put("default", object);
+                    }
+                }
+            }
+        }
+
+        return (String[]) list.toArray(new String[0]);
+    }
+
+    /**
+     * Gets class that handles specific DAV request.
+     *
+     * @param id Method name (e.g. PROPFIND, MKCOL)
+     * @return applicable class, if it has been configured, null otherwise
+     */
+    public DAVComponent getMethod(String id) {
+        return (DAVComponent) methods.get(id);
+    }
+
+    /**
+     * Gets class that handles specific collection-level operation for WebAdmin.
+     *
+     * @param id Opration id
+     * @return applicable class, if it has been configured, null otherwise
+     */
+    public HtmlCollectionViewer getCollectionViewer(String id) {
+        if (id == null || id.length() == 0) {
+            id = "default";
+        }
+
+        return (HtmlCollectionViewer) colViewers.get(id);
+    }
+
+    /**
+     * Gets class that handles specific resource-level operation for WebAdmin.
+     *
+     * @param id Opration id
+     * @return applicable class, if it has been configured, null otherwise
+     */
+    public HtmlResourceViewer getResourceViewer(String id) {
+        if (id == null || id.length() == 0) {
+            id = "default";
+        }
+
+        return (HtmlResourceViewer) resViewers.get(id);
+    }
+
+    /**
+     * Gets class that handles specific database-level operation for WebAdmin.
+     *
+     * @param id Opration id
+     * @return applicable class, if it has been configured, null otherwise
+     */
+    public HtmlDatabaseViewer getDatabaseViewer(String id) {
+        if (id == null || id.length() == 0) {
+            id = "default";
+        }
+
+        return (HtmlDatabaseViewer) dbViewers.get(id);
+    }
+
+    /**
+     * Gets all supported methods.
+     *
+     * @return Array of all supported WebDAV methods.
+     */
+    public static String[] getMethods() {
+        return methodsList;
+    }
+
+    /**
+     * Gets all supported database-level operations.
+     *
+     * @return Array of all supported database-level operations.
+     */
+    public static String[] getDatabaseViewers() {
+        return dbViewersList;
+    }
+
+    /**
+     * Gets all supported collection-level operations.
+     *
+     * @return Array of all supported collection-level operations.
+     */
+    public static String[] getCollectionViewers() {
+        return colViewersList;
+    }
+
+    /**
+     * Gets all supported resource-level operations.
+     *
+     * @return Array of all supported resource-level operations.
+     */
+    public static String[] getResourceViewers() {
+        return resViewersList;
+    }
+}

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/WebAdminManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/WebAdminManager.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision Author Date

Modified: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/WebAdminServlet.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/WebAdminServlet.java?view=diff&rev=541504&r1=541498&r2=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/WebAdminServlet.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/WebAdminServlet.java Thu May 24 18:43:39 2007
@@ -19,21 +19,28 @@
 
 package org.apache.xindice.webadmin;
 
-import java.io.File;
 import java.io.IOException;
+import java.io.FileInputStream;
+import java.io.InputStream;
 
 import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
+import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.avalon.fortress.ContainerManager;
-import org.apache.avalon.fortress.impl.DefaultContainerManager;
-import org.apache.avalon.fortress.util.FortressConfig;
-import org.apache.avalon.framework.container.ContainerUtil;
 import org.apache.xindice.server.XindiceServlet;
-import org.apache.xindice.core.Database;
+import org.apache.xindice.xml.dom.DOMParser;
+import org.apache.xindice.core.DBException;
+import org.apache.xindice.core.Collection;
+import org.apache.xindice.webadmin.webdav.components.DAVComponent;
+import org.apache.xindice.webadmin.webdav.WebdavStatus;
+import org.apache.xindice.webadmin.webdav.DAVRequest;
+import org.apache.xindice.webadmin.webdav.DAVResponse;
+import org.apache.xindice.webadmin.util.MimeTable;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Document;
 
 /**
  * @author <a href="mailto:[email protected]">Jan Metzner</a>
@@ -41,71 +48,144 @@
  */
 public class WebAdminServlet extends XindiceServlet {
 
-	protected WebAdminContainer m_container;
-	protected ContainerManager m_containerManager;
+    protected WebAdminManager mgr;
 
-	/**
-	 * Initializes Servlet and creates a WebAdminContainer instance
-	 *
-	 * @exception ServletException if an error occurs
-	 */
-	public void init(ServletConfig servletConfig) throws ServletException {
-		super.init(servletConfig);
-		try {
-
-			ServletContext servletContext = servletConfig.getServletContext();
-
-			final FortressConfig config = new FortressConfig();
-			config.setContainerClass(WebAdminContainer.class);
-			config.setContextDirectory( servletContext.getRealPath("/") );
-			config.setWorkDirectory( (File) servletContext
-				.getAttribute( "javax.servlet.context.tempdir" ) );
-			config.setContainerConfiguration(
-				"resource://org/apache/xindice/webadmin/WebAdmin.xconf");
-			config.setLoggerManagerConfiguration(
-				"resource://org/apache/xindice/webadmin/WebAdmin.xlog");
-
-			m_containerManager = new DefaultContainerManager( config.getContext() );
-			ContainerUtil.initialize(m_containerManager);
-
-			m_container = (WebAdminContainer)m_containerManager.getContainer();
-		} catch(Exception e)	{
-			throw new ServletException( "Error during initialization", e );
-		}
-	}
-
-	/**
-	 * Pass all servlet requests through to container to be handled.
-	 *
-	 * @param req a HttpServletRequest instance
-	 * @param res a HttpServletResponse instance
-	 * @exception IOException if an IO error occurs
-	 * @exception ServletException if a servlet error occurs
-	 */
-	public void service(HttpServletRequest req, HttpServletResponse res)
-		throws IOException, ServletException {
-
-		// get request path
-		String path = req.getPathInfo();
-		if(path == null) {
-			path = "";
-		}
-
-		// xmlrpc request are handled by the XindiceServlet
-		if(req.getMethod().equalsIgnoreCase("POST") && path.length() < 2) {
-			super.doPost(req, res);
-		} else {
-			// HACK Get first database and use it. Should be changed to support multiple databases
-            String[] databases = Database.listDatabases();
-			m_container.handleRequest(req, res, Database.getDatabase(databases[0]));
-		}
-	}
-
-	/**
-	 * Disposes of container manager and container instance.
-	 */
-	public void destroy() {
-		super.destroy();
-		ContainerUtil.dispose(m_containerManager);
-	}
+    private static final Log log = LogFactory.getLog(WebAdminServlet.class);
+    private static final String WEBADMIN_CONFIGURATION = "webadmin.configuration";
+    private static final String MIMETABLE_CONFIGURATION = "mimetable.configuration";
+
+    /**
+     * Initializes Servlet and creates a WebAdminContainer instance
+     *
+     * @exception ServletException if an error occurs
+     */
+    public void init(ServletConfig servletConfig) throws ServletException {
+
+        super.init(servletConfig);
+        try {
+            String path = servletConfig.getInitParameter(WEBADMIN_CONFIGURATION);
+            Document configuration = loadFile(path, servletConfig);
+            mgr = new WebAdminManager(configuration);
+        } catch(Exception e) {
+            throw new ServletException("Could not process WebAdmin configuration", e);
+        }
+
+        try {
+            String path = servletConfig.getInitParameter(MIMETABLE_CONFIGURATION);
+            Document configuration = loadFile(path, servletConfig);
+            MimeTable.addMimeConfig(configuration);
+
+        } catch(Exception e) {
+            log.error("Could not process Mime Table configuration", e);
+        }
+    }
+
+    private Document loadFile(String path, ServletConfig config) throws Exception {
+        InputStream inputStream = null;
+
+        try {
+            if (path.startsWith("/")) { // Absolute file path
+                log.debug("Loading configuration from filesystem path " + path);
+                inputStream = new FileInputStream(path);
+            } else {
+                // Relative (to the context) path
+                log.debug("Loading configuration from context path " + path);
+                ServletContext context = config.getServletContext();
+                inputStream = context.getResourceAsStream("/" + path);
+            }
+
+            Document configuration = null;
+            if (inputStream != null) {
+                configuration = DOMParser.toDocument(inputStream);
+            }
+
+            return configuration;
+        } finally {
+            try {
+                if (inputStream != null) {
+                    inputStream.close();
+                }
+            } catch (IOException ignored) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Pass all servlet requests through to container to be handled.
+     *
+     * @param req a HttpServletRequest instance
+     * @param res a HttpServletResponse instance
+     * @exception IOException if an IO error occurs
+     * @exception ServletException if a servlet error occurs
+     */
+    public void service(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
+
+        // get request path
+        String path = req.getPathInfo();
+
+        // xmlrpc request are handled by the XindiceServlet
+        if(req.getMethod().equalsIgnoreCase("POST") && (path == null || path.length() < 2)) {
+            super.doPost(req, res);
+        } else {
+            process(req, res);
+        }
+    }
+
+    private void process(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
+
+        // get request path
+        String path = req.getPathInfo();
+
+        // get content
+        Location target;
+        try {
+            target = new Location(path);
+        } catch (DBException e) {
+            log.error(e);
+            throw new ServletException(e);
+        }
+
+        Collection col = target.getCollection();
+        String resource = target.getName();
+
+        // choose html interface
+        String viewer = req.getParameter("viewer");
+
+        if (viewer == null || viewer.length() == 0) { // not html request
+            DAVComponent method = mgr.getMethod(req.getMethod());
+
+            if (method == null) {
+                // method is not supported
+                if (log.isWarnEnabled()) {
+                    log.warn("Method " + req.getMethod() + " is not supported.");
+                }
+                res.setStatus(WebdavStatus.SC_NOT_IMPLEMENTED);
+                return;
+            }
+
+            DAVRequest request = new DAVRequest(req);
+            DAVResponse response = new DAVResponse(res);
+            method.execute(request, response, target);
+        } else { // html request
+            if (col == null) {
+                if (!"/".equals(path)) {
+                    String redirect = req.getContextPath() + req.getServletPath() + "/?viewer=" + viewer;
+                    res.sendRedirect(redirect);
+                }
+
+                mgr.getDatabaseViewer(viewer).execute(req, res);
+            } else if (resource == null) {
+                // redirect if path does not end with /
+                if (!path.endsWith("/")) {
+                    String redirect = req.getContextPath() + req.getServletPath() + path + "/?viewer=" + viewer;
+                    res.sendRedirect(redirect);
+                }
+
+                mgr.getCollectionViewer(viewer).execute(req, res, col);
+            } else {
+                mgr.getResourceViewer(viewer).execute(req, res, col, resource);
+            }
+        }
+    }
 }

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/WebAdminServlet.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu May 24 18:43:39 2007
@@ -1 +1 @@
-Author Date Id Revision
+Id Revision Author Date

Modified: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/util/CollectionConfigurationHelper.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/util/CollectionConfigurationHelper.java?view=diff&rev=541504&r1=541498&r2=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/util/CollectionConfigurationHelper.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/util/CollectionConfigurationHelper.java Thu May 24 18:43:39 2007
@@ -14,69 +14,155 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
- * $Id$
- */ 
+ * CVS $Id$
+ */
 
 package org.apache.xindice.webadmin.util;
 
 import org.apache.xindice.core.Collection;
 import org.apache.xindice.util.Configuration;
-import org.apache.xindice.util.XindiceException;
+import org.apache.xindice.util.ReadOnlyException;
+import org.apache.xindice.xml.TextWriter;
+import org.apache.xindice.xml.dom.DocumentImpl;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 
 /** 
- *  
+ * Helper class for oprations on collection configuration
+ *
  * @author <a href="mailto:[email protected]">Jan Metzner</a>
  * @version $Id$ 
  */
 
-public interface CollectionConfigurationHelper {
-
-	/** Role identifying Component */
-    String ROLE = CollectionConfigurationHelper.class.getName();
+public class CollectionConfigurationHelper {
 
+    private static final Log log = LogFactory.getLog(CollectionConfigurationHelper.class);
     public static final String CONF_ELE = "collection";
-    
-	public static final String COL_NAME_ATTR = "name";
-
+    public static final String COL_NAME_ATTR = "name";
     public static final String INLINE_META_ATTR = "inline-metadata";
-
     public static final String COMPRESSED_ATTR = "compressed";
-
     public static final String FILER_ELE = "filer";
-
     public static final String FILER_CLASS_ATTR = "class";
-
     public static final boolean DEFAULT_INLINE_META = true;
-
     public static final boolean DEFAULT_COMPRESSED = true;
+    public static final String DEFAULT_FILER_CLASS = "org.apache.xindice.core.filer.BTreeFiler";
 
-    public static final String DEFAULT_FILER_CLASS =
-        "org.apache.xindice.core.filer.BTreeFiler";
-        
-    public boolean isAutoEnableInlineMeta();
-    
-	public boolean getDefaultInlineMetadata();
-	
-	public boolean getDefaultCompressed();
-	
-	public String getDefaultFilerClass();
-	
-	public boolean isInlineMetaEnabled(final Collection col);
-
-    public Configuration createDefaultConfiguration(String name);
-
-    public Configuration createConfiguration(
-        String name,
-        String compressed,
-        String inlineMeta,
-        String filerClass);
-
-    public void enableCollectionInlineMetadata(Collection col)
-        throws XindiceException;
-
-    public Configuration copyConfiguration(final Configuration srcConfig);
-
-    public Configuration copyConfiguration(
-        String name,
-        final Configuration srcConfig);
-}
\ No newline at end of file
+    /**
+     * Configures the CollectionConfigurationHelper with the default 
+     * Collection Configuration. Example:
+     * <pre>
+     * &lt;col-config id="col-config" autoenableinlinemeta="true"&gt;
+     *   &lt;collection compressed="true" inline-meta="true"&gt;
+     *     &lt;filer class="org.apache.xindice.core.filer.BTreeFiler" /&gt;
+     *   &lt;/collection&gt;
+     * &lt;/col-config&gt;
+     * </pre>
+     * A name Attribute will be ignored.
+     * If the Attribute autoenableinlinemeta is set true, the Collection is not Inline 
+     * Metadata enabled and a Binary is inserted, the Collection will be automatically
+     * Inline Metadata enabled.
+     */
+    public static boolean getDefaultInlineMetadata() {
+        return DEFAULT_INLINE_META;
+    }
+
+    public static boolean getDefaultCompressed() {
+        return DEFAULT_COMPRESSED;
+    }
+
+    public static String getDefaultFilerClass() {
+        return DEFAULT_FILER_CLASS;
+    }
+
+    public static boolean isInlineMetaEnabled(final Collection col) {
+        Configuration config = col.getConfig();
+        return config.getBooleanAttribute(INLINE_META_ATTR, false);
+    }
+
+    public static Configuration createDefaultConfiguration(String name) {
+        return createConfiguration(name, null, null, null);
+    }
+
+    public static Configuration createConfiguration(String name, String compressed, String inlineMeta, String filerClass) {
+        Document doc = new DocumentImpl();
+        Element colEle = doc.createElement(CONF_ELE);
+        if (name == null || name.length() == 0) {
+            throw new IllegalArgumentException("null name");
+        }
+        colEle.setAttribute(COL_NAME_ATTR, name);
+        if (compressed == null || (!compressed.equalsIgnoreCase("true") && !compressed.equalsIgnoreCase("false"))) {
+            compressed = Boolean.toString(DEFAULT_COMPRESSED);
+        }
+        colEle.setAttribute(COMPRESSED_ATTR, compressed);
+        if (inlineMeta == null || (!inlineMeta.equalsIgnoreCase("true") && !inlineMeta.equalsIgnoreCase("false"))) {
+            inlineMeta = Boolean.toString(DEFAULT_INLINE_META);
+        }
+        colEle.setAttribute(INLINE_META_ATTR, inlineMeta);
+        doc.appendChild(colEle);
+        Element filEle = doc.createElement(FILER_ELE);
+        if (filerClass == null || filerClass.length() == 0) {
+            filerClass = DEFAULT_FILER_CLASS;
+        }
+        filEle.setAttribute(FILER_CLASS_ATTR, filerClass);
+        colEle.appendChild(filEle);
+        if (log.isDebugEnabled()) {
+            log.debug("Created Configuration: \n" + TextWriter.toString(doc));
+        }
+        return new Configuration(doc.getDocumentElement(), false);
+    }
+
+    public static Configuration copyConfiguration(final Configuration srcConfig) {
+        Configuration newConfig = createConfiguration();
+        try {
+            return copyConfigurationContent(srcConfig, newConfig);
+        } catch (ReadOnlyException e) {
+            log.error(e);
+            return null;
+        }
+    }
+
+    public static Configuration copyConfiguration(String name, final Configuration srcConfig) {
+        Configuration destConfig = createConfiguration();
+        try {
+            copyConfigurationContent(srcConfig, destConfig);
+            destConfig.setAttribute(COL_NAME_ATTR, name);
+        } catch (ReadOnlyException e) {
+            // ignore, cannot happen
+        }
+
+        return destConfig;
+    }
+
+    private static Configuration copyConfigurationContent(final Configuration srcConfig, Configuration destConfig)
+        throws ReadOnlyException {
+
+        if (srcConfig.hasAttributes()) {
+            String[] attrs = srcConfig.listAttributes();
+            for (int i = 0; i < attrs.length; i++) {
+                destConfig.setAttribute(attrs[i], srcConfig.getAttribute(attrs[i]));
+            }
+        }
+        if (srcConfig.hasValue()) {
+            String value = srcConfig.getValue(null);
+            if (value != null) {
+                destConfig.setValue(value);
+            }
+        }
+        if (srcConfig.hasChildren()) {
+            Configuration[] childConf = srcConfig.getChildren();
+            for (int i = 0; i < childConf.length; i++) {
+                Configuration childDestConfig = destConfig.getChild(childConf[i].getName(), true);
+                copyConfigurationContent(childConf[i], childDestConfig);
+            }
+        }
+
+        return destConfig;
+    }
+
+    private static Configuration createConfiguration() {
+        Document doc = new DocumentImpl();
+        return new Configuration(doc.createElement(CONF_ELE), false);
+    }
+}

Modified: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/util/DAVOperations.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/util/DAVOperations.java?view=diff&rev=541504&r1=541498&r2=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/util/DAVOperations.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/util/DAVOperations.java Thu May 24 18:43:39 2007
@@ -19,80 +19,232 @@
 
 package org.apache.xindice.webadmin.util;
 
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.avalon.framework.service.ServiceException;
 import org.apache.xindice.core.Collection;
 import org.apache.xindice.core.DBException;
+import org.apache.xindice.core.FaultCodes;
+import org.apache.xindice.core.data.Key;
+import org.apache.xindice.core.data.Entry;
+import org.apache.xindice.webadmin.webdav.WebdavStatus;
+import org.apache.xindice.webadmin.Location;
+import org.apache.xindice.util.Configuration;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Document;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Collections;
 
-/** 
- * Some usefull Operations like Copy or Move.
- * 
+/**
+ * Helper for copy/move operations.
+ *
  * @author <a href="mailto:[email protected]">Jan Metzner</a>
- * @version $Id$ 
+ * @version $Id$
  */
-public interface DAVOperations {
 
-	/** Role identifying Component */
-	String ROLE = DAVOperations.class.getName();
-	
-    /**
-     * Copies the collection or resource spcified by parentCol and name
-     * to the destination specified by the destination header of the request.
-     *
-     * @param req servlet request.
-     * @param parentCol parent collection.
-     * @param name name of the source resource/collection
-     * @return WEBDAV Status Code.
-     * @throws DBException while writing the new resource/collection.
-     */
-    public abstract int copy(
-        HttpServletRequest req,
-        Collection parentCol,
-        String name)
-        throws DBException, ServiceException;
-        
-    /**
-     * gets the destination path header from Copy and Move requests.
-     *
-     * @param req servlet request.
-     * @return destination path or null if the header does not exits.
-     */
-    public abstract String getDestinationPath(HttpServletRequest req);
-    
-    /**
-     * Parses the overwrite header of the given request.
-     *
-     * @param req servlet request.
-     * @return the boolean value of the overwrite header
-     *         (true if the header does not exist).
-     */
-    public abstract boolean getOverwrite(HttpServletRequest req);
-    
+public class DAVOperations {
+
+    private static final Log log = LogFactory.getLog(DAVOperations.class);
+
     /**
-     * copies the entire collection to a new destination.
-     *
-     * @param srcCol source collection.
-     * @param destParentCol parent collection of the destination.
-     * @param name name of the new collection.
-     * @throws DBException while creating the new collection.
-     * @return the new created collection.
+     * Copies collection to the new destination
+     * @param col Collection to be copied
+     * @param dest Destination path (includes DB name)
+     * @param overwrite true if previously existed collection at dest path can be overwritten
+     * @return
+     * @throws DBException
      */
-    public abstract Collection copyCollection(
-        Collection srcCol,
-        Collection destParentCol,
-        String name)
-        throws DBException, ServiceException;
-        
+    public static Map copy(Collection col, String dest, boolean overwrite, boolean deep) throws DBException {
+
+        Location destLocation = new Location(dest);
+        Collection destCollection = destLocation.getCollection();
+        String destName = destLocation.getName();
+        Map results = new HashMap();
+
+        if (destLocation.isRoot()) {
+            results.put(dest, new Integer(WebdavStatus.SC_BAD_REQUEST));
+            return results;
+        } else if (destCollection == null) {
+            // either intermidiate collection does not exist or destination points to
+            // the first level collection (database).
+            results.put(dest, new Integer(WebdavStatus.SC_CONFLICT));
+            return results;
+        } else if (deep && destCollection.getCanonicalName().startsWith(col.getCanonicalName())) {
+            // destination points to a location inside target collection subtree.
+            // deep copy does not make sense in that case
+            results.put(dest, new Integer(WebdavStatus.SC_FORBIDDEN));
+            return results;
+        }
+
+        // FIXME: the operations are not atomic, they can fail because of another
+        // thread deleting or creating collections. Introduce locks.
+        if (destName != null) { // destination collection does not exist
+
+            results.putAll(copyCollection(col, destCollection, destName, deep));
+            if (results.size() == 0) {
+                results.put(dest, new Integer(WebdavStatus.SC_CREATED));
+            }
+        } else { // existing collection
+
+            if (overwrite) {
+                // overwrites the collection
+                String name = destCollection.getName();
+                Collection parent = destCollection.getParentCollection();
+                // delete collection
+                parent.dropCollection(destCollection);
+                results.putAll(copyCollection(col, parent, name, deep));
+                if (results.size() == 0) {
+                    results.put(dest, new Integer(WebdavStatus.SC_NO_CONTENT));
+                }
+            } else {
+                results.put(dest, new Integer(WebdavStatus.SC_PRECONDITION_FAILED));
+            }
+
+        }
+
+        return results;
+    }
+
     /**
-     * copies the collection content (resources and collections).
-     *
-     * @param srcCol source collection.
-     * @param destCol destination collection.
-     * @throws DBException while creating the new content.
+     * Copies a resource to a new location.
+     * @param col Source collection
+     * @param name Resource name
+     * @param dest Path to the new location. It includes db name and new resource name
+     * @param overwrite true if previously existed resource at dest path can be overwritten
+     * @return
+     * @throws DBException
      */
-    public abstract void copyCollectionContent(
-        Collection srcCol,
-        Collection destCol)
-        throws DBException, ServiceException;
-}
\ No newline at end of file
+    public static int copy(Collection col, String name, String dest, boolean overwrite) throws DBException {
+
+        Location destLocation = new Location(dest);
+        Collection destCollection = destLocation.getCollection();
+        String destName = destLocation.getName();
+
+        if (destLocation.isRoot()) {
+            // resource cannot be added to root directly, database has to be created manually
+            return WebdavStatus.SC_FORBIDDEN;
+        } else if (destCollection == null) {
+            return WebdavStatus.SC_CONFLICT;
+        } else if (col == destCollection && name.equals(destName)) {
+            return WebdavStatus.SC_FORBIDDEN;
+        }
+
+        // get source
+        Entry object = col.getEntry(name);
+        if (object == null) {
+            return WebdavStatus.SC_NOT_FOUND;
+        }
+
+        int status;
+        try {
+            if (object.getEntryType() == Entry.BINARY) { // insert Binary
+                if (overwrite) {
+                    if (destCollection.setBinary(new Key(destName), (byte[]) object.getValue())) {
+                        status = WebdavStatus.SC_CREATED;
+                    } else {
+                        status = WebdavStatus.SC_NO_CONTENT;
+                    }
+                } else {
+                    destCollection.insertBinary(destName, (byte[]) object.getValue());
+                    status = WebdavStatus.SC_CREATED;
+                }
+            } else if (object.getEntryType() == Entry.DOCUMENT) {
+                if (overwrite) {
+                    if (destCollection.setDocument(new Key(destName), (Document) object.getValue())) {
+                        status = WebdavStatus.SC_CREATED;
+                    } else {
+                        status = WebdavStatus.SC_NO_CONTENT;
+                    }
+                } else {
+                    destCollection.insertDocument(destName, (Document) object.getValue());
+                    status = WebdavStatus.SC_CREATED;
+                }
+            } else {
+                // placeholder, won't get here
+                status = WebdavStatus.SC_FORBIDDEN;
+            }
+        } catch (DBException e) {
+            if (e.faultCode == FaultCodes.COL_DUPLICATE_RESOURCE) {
+                status = WebdavStatus.SC_PRECONDITION_FAILED;
+            } else if (e.faultCode == FaultCodes.COL_NO_FILER) {
+                status = WebdavStatus.SC_FORBIDDEN;
+            } else if (e.faultCode == FaultCodes.COL_COLLECTION_NOT_FOUND) {
+                status = WebdavStatus.SC_CONFLICT;
+            } else if (e.faultCode == FaultCodes.COL_CANNOT_STORE) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Collection Inline Metadata is not enabled!");
+                }
+                status = WebdavStatus.SC_FORBIDDEN;
+            } else {
+                throw e;
+            }
+        }
+
+        return status;
+    }
+
+    private static Map copyCollection(Collection col, Collection parent, String name, boolean deep)
+            throws DBException {
+
+        Configuration config = CollectionConfigurationHelper.copyConfiguration(name, col.getConfig());
+        Collection newCol = parent.createCollection(name, config);
+
+        if (deep) {
+            return copyCollectionContent(col, newCol);
+        } else {
+            return Collections.EMPTY_MAP;
+        }
+    }
+
+    private static Map copyCollectionContent(Collection srcCol, Collection destCol) throws DBException {
+        HashMap result = new HashMap();
+
+        // copy resources
+        String[] resList = srcCol.listDocuments();
+        for (int i = 0; i < resList.length; i++) {
+            Entry object = srcCol.getEntry(resList[i]);
+            if (object.getEntryType() == Entry.DOCUMENT) {
+                destCol.setDocument(resList[i], (Document) object.getValue());
+            } else {
+                destCol.setBinary(resList[i], (byte[]) object.getValue());
+            }
+        }
+
+        // copy child collections content collections
+        /* From the specification:
+           If an error occurs while copying an internal collection, the server MUST NOT
+           copy any resources identified by members of this collection (i.e., the server
+           must skip this subtree), as this would create an inconsistent namespace.
+           After detecting an error, the COPY operation SHOULD try to finish as much
+           of the original copy operation as possible (i.e., the server should still
+           attempt to copy other subtrees and their members, that are not descendents
+           of an error-causing collection).
+          */
+        String[] colList = srcCol.listCollections();
+        for (int i = 0; i < colList.length; i++) {
+            Collection srcChild = srcCol.getCollection(colList[i]);
+            Collection destChild = destCol.getCollection(colList[i]);
+            try {
+                result.putAll(copyCollectionContent(srcChild, destChild));
+            } catch (DBException e) {
+                int code;
+                if (e.faultCode == FaultCodes.COL_NO_FILER) {
+                    code = WebdavStatus.SC_FORBIDDEN;
+                } else if (e.faultCode == FaultCodes.COL_COLLECTION_NOT_FOUND) {
+                    code = WebdavStatus.SC_CONFLICT;
+                } else if (e.faultCode == FaultCodes.COL_CANNOT_STORE) {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Collection Inline Metadata is not enabled!");
+                    }
+                    code = WebdavStatus.SC_FORBIDDEN;
+                } else {
+                    throw e;
+                }
+
+                result.put(destChild.getCanonicalName(), new Integer(code));
+            }
+        }
+
+        return result;
+    }
+}

Modified: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/util/MimeTable.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/util/MimeTable.java?view=diff&rev=541504&r1=541498&r2=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/util/MimeTable.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/util/MimeTable.java Thu May 24 18:43:39 2007
@@ -14,54 +14,192 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
- * $Id$
+ * CVS $Id$
  */
 
 package org.apache.xindice.webadmin.util;
 
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.util.Hashtable;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.apache.xindice.xml.dom.DOMParser;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+
 /**
- * MimeTable maps a file extension to a mime type. 
+ * MimeTable maps a file extension to a mime type.
  *
  * @author <a href="mailto:[email protected]">Jan Metzner</a>
  * @version $Id$
  */
-public interface MimeTable {
-	
-	/** Role identifying Component */	
-	String ROLE = MimeTable.class.getName();
-	
-	/** the default mime type for binaries */
-	public static final String BINARY_MIME_TYPE = "application/octet-stream";
-
-	/** the default mime type for xml documents */
-	public static final String XML_MIME_TYPE = "text/xml";
-
-	/**
-	 * returns the mime type of the given object.
-	 * 
-	 * @param resource the object. 
-	 * @param name the name of the object.
-	 * @return mime type for this object.
-	 */
-	public abstract String getMimeType(Object resource, String name);
-	
-	/**
-	 * returns the mime type for the given name.
-	 * if no mime for this name is available the default xml mime type is returned.
-	 * 
-	 * @param recourceName the name of the resource.
-	 * @return mime type for this resource name.
-	 */
-	public abstract String getMimeType(String recourceName);
-	
-	/**
-	 * returns the mime type for the given name.
-	 * if no mime for this name is available the parameter defaultXml specifies if
-	 * the xml mime type or the binary mime type are returned.
-	 * 
-	 * @param resourceName
-	 * @param defaultXml
-	 * @return
-	 */
-	public abstract String getMimeType(String resourceName, boolean defaultXml);
-}
\ No newline at end of file
+public class MimeTable {
+
+    /** the default mime type for binaries */
+    public static final String BINARY_MIME_TYPE = "application/octet-stream";
+
+    /** the default mime type for xml documents */
+    public static final String XML_MIME_TYPE = "text/xml";
+
+    /** holds the extensions/mime types */
+    protected static Hashtable mimeMappings = new Hashtable();
+
+    private final static Log log = LogFactory.getLog(MimeTable.class);
+
+    /**
+     * Configures the Mime table.
+     * the configuration can look like the Configuration in the
+     * addMimeConfig(Configuration config) Method<br />
+     * <br/>
+     * or if the Configuration should be loaded out of an extra file:
+     * <pre>
+     * &lt;mime location="/some/path"&gt;
+     * </pre>
+     * or if the Configuration should be loaded out of the Classpath:
+     * <pre>
+     * &lt;mime location="resource://org.a.MyFile"&gt;
+     * </pre>
+     */
+    public static void configure(String location) {
+        // load mime table
+        boolean loadFromClasspath = false;
+        if (location.startsWith("resource://")) {
+            loadFromClasspath = true;
+            location = location.substring(11);
+        }
+
+        try {
+            if (loadFromClasspath) {
+                InputStream is = Thread.currentThread().getContextClassLoader().getResource(location).openStream();
+                if (log.isDebugEnabled()) {
+                    log.debug("Load Configuration from Classpath: " + location);
+                }
+                addMimeConfig(DOMParser.toDocument(is));
+            } else {
+                if (log.isDebugEnabled()) {
+                    log.debug("Load Configuration from File: " + location);
+                }
+                addMimeConfig(DOMParser.toDocument(location));
+            }
+        } catch (Exception e) {
+            log.error("Could not load MimeTable configuration", e);
+        }
+    }
+
+    /**
+     * Add the given mime Document to this mime table.
+     * the mime Document looks like this:
+     * <pre>
+     * &lt;mime&gt;
+     *  &lt;mime-mapping&gt;
+     *   &lt;extension&gt;xml&lt;/extension&gt;
+     *   &lt;mime-type&gt;xml&lt;/mime-type&gt;
+     *  &lt;/mime-mapping&gt;
+     * ...
+     * &lt;/mime&gt;
+     * </pre>
+     *
+     * @param doc mime config.
+     */
+    public static void addMimeConfig(Document doc) {
+        NodeList mapping = doc.getChildNodes();
+        for (int i = 0; i < mapping.getLength(); i++) {
+            NodeList thisMapping = mapping.item(i).getChildNodes();
+            String ext = "";
+            String type = "";
+            for (int j = 0; j < thisMapping.getLength(); j++) {
+                if (thisMapping.item(j).getNodeName().equalsIgnoreCase("extension")) {
+                    ext = thisMapping.item(j).getNodeValue();
+                } else if (thisMapping.item(j).getNodeName().equalsIgnoreCase("mime-type")) {
+                    type = thisMapping.item(j).getNodeValue();
+                }
+            }
+            mimeMappings.put(ext, type);
+        }
+    }
+
+    /**
+     * Returns the mime type for the given name.
+     * If no mime for this name is available the parameter defaultXml specifies if
+     * the xml mime type or the binary mime type are returned.
+     *
+     * @param resourceName
+     * @return mime type for this resource name
+     */
+    public static String getMimeType(String resourceName) {
+        int split = resourceName.lastIndexOf('.');
+        String mime = null;
+        if (split > 0) {
+            mime = (String) mimeMappings.get(resourceName.substring(split + 1));
+        }
+
+        if (mime != null) {
+            return mime;
+        } else {
+            return BINARY_MIME_TYPE;
+        }
+    }
+
+    private static void writeMappingAsXml(HashMap mappings, Writer out) throws IOException {
+        out.write("<?xml version=\"1.0\"?>\n");
+        out.write("<mime>\n");
+        for (Iterator i = mappings.keySet().iterator(); i.hasNext();) {
+            String ext = (String) i.next();
+            String type = (String) mappings.get(ext);
+
+            out.write("    <mime-mapping>\n");
+            out.write("        <extension>" + ext + "</extension>\n");
+            out.write("        <mime-type>" + type + "</mime-type>\n");
+            out.write("    </mime-mapping>\n");
+        }
+        out.write("</mime>");
+    }
+
+    private static HashMap parseApacheHttpdMime(String location) throws IOException {
+        HashMap mappings = new HashMap();
+        BufferedReader f = new BufferedReader(new FileReader(location));
+        String line;
+        while ((line = f.readLine()) != null) {
+            int startComment = line.indexOf('#');
+            if (startComment >= 0) {
+                line = line.substring(0, startComment);
+            }
+            line = line.trim();
+            String[] parsedLine = line.split(" |\\t");
+            if (parsedLine.length >= 2) {
+                for (int i = 1; i < parsedLine.length; i++) {
+                    if (parsedLine[i].length() > 0) {
+                        mappings.put(parsedLine[i], parsedLine[0]);
+                    }
+                }
+            }
+        }
+        return mappings;
+    }
+
+    private static void convertApacheHttpdMimeToXml(String source, String destination) throws IOException {
+        HashMap mappings = parseApacheHttpdMime(source);
+        BufferedWriter output = new BufferedWriter(new FileWriter(destination));
+        writeMappingAsXml(mappings, output);
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (args.length != 2) {
+            System.out.println("Convert Apache httpd mime file to a xml file");
+            System.out.println("Usage: java org.apache.xindice.webadmin.util.MimeTable httpdfile xmlfile");
+            System.exit(1);
+        }
+
+        convertApacheHttpdMimeToXml(args[0], args[1]);
+        System.out.println("Converted " + args[0] + " to " + args[1]);
+    }
+}

Modified: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlCollectionViewer.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlCollectionViewer.java?view=diff&rev=541504&r1=541498&r2=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlCollectionViewer.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlCollectionViewer.java Thu May 24 18:43:39 2007
@@ -36,17 +36,12 @@
 public interface HtmlCollectionViewer {
 
 	/**
-	 * Role identifying Component
-	 */	
-	String ROLE = HtmlCollectionViewer.class.getName();
-	
-	/**
-	 * executes request to a collection.
+	 * Executes request to a collection.
 	 * 
 	 * @param req request from servlet.
 	 * @param res servlet response.
 	 * @param col requested collection (not null).
 	 */
-	public void execute(HttpServletRequest req, HttpServletResponse res,
-		Collection col) throws ServletException, IOException; 
+	public void execute(HttpServletRequest req, HttpServletResponse res, Collection col)
+            throws ServletException, IOException;
 }

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlCollectionViewer.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu May 24 18:43:39 2007
@@ -1 +1 @@
-Author Date Id Revision
+Id Revision Author Date

Added: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlDatabaseViewer.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlDatabaseViewer.java?view=auto&rev=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlDatabaseViewer.java (added)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlDatabaseViewer.java Thu May 24 18:43:39 2007
@@ -0,0 +1,39 @@
+/*
+ * 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 org.apache.xindice.webadmin.viewer;
+
+import org.apache.xindice.core.Collection;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletException;
+import java.io.IOException;
+
+/**
+ * Xindice Html Database Interface Component.
+ */
+public interface HtmlDatabaseViewer {
+
+    /**
+     * executes request to a collection.
+     *
+     * @param req request from servlet.
+     * @param res servlet response.
+     */
+    public void execute(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException;
+}

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlDatabaseViewer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlDatabaseViewer.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision Author Date

Modified: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlResourceViewer.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlResourceViewer.java?view=diff&rev=541504&r1=541498&r2=541504
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlResourceViewer.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlResourceViewer.java Thu May 24 18:43:39 2007
@@ -34,19 +34,15 @@
  * @version $Id$
  */
 public interface HtmlResourceViewer {
-	
-	/** Role identifying Component */
-	String ROLE = HtmlResourceViewer.class.getName();
-	
+
 	/**
 	 * executes request to a resource.
 	 * 
 	 * @param req request from servlet.
 	 * @param res servlet response.
-	 * @param parentCol parent collection of the requested resource (not null).
+	 * @param col parent collection of the requested resource (not null).
 	 * @param resourceName name of the requested resource.
 	 */
-	public void execute(HttpServletRequest req, HttpServletResponse res,
-	 	Collection parentCol, String resourceName)
+	public void execute(HttpServletRequest req, HttpServletResponse res, Collection col, String resourceName)
 	 	throws ServletException, IOException;
 }

Propchange: xml/xindice/trunk/java/src/org/apache/xindice/webadmin/viewer/HtmlResourceViewer.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu May 24 18:43:39 2007
@@ -1 +1 @@
-Author Date Id Revision
+Id Revision Author Date
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.