Added: archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/pom.xml URL: http://svn.apache.org/viewvc/archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/pom.xml?rev=743242&view=auto ============================================================================== --- archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/pom.xml (added) +++ archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/pom.xml Wed Feb 11 06:11:40 2009 @@ -0,0 +1,26 @@ +<?xml version="1.0"?> +<project> + <parent> + <artifactId>archiva-web</artifactId> + <groupId>org.apache.archiva</groupId> + <version>1.2-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <groupId>org.apache.archiva</groupId> + <artifactId>archiva-repository-servlet</artifactId> + <name>Archiva Web :: Repository Servlet</name> + <dependencies> + <dependency> + <groupId>org.apache.archiva</groupId> + <artifactId>archiva-repository-api</artifactId> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + </dependencies> +</project>
Added: archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/src/main/java/org/apache/archiva/web/servlet/HttpRepositoryContext.java URL: http://svn.apache.org/viewvc/archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/src/main/java/org/apache/archiva/web/servlet/HttpRepositoryContext.java?rev=743242&view=auto ============================================================================== --- archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/src/main/java/org/apache/archiva/web/servlet/HttpRepositoryContext.java (added) +++ archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/src/main/java/org/apache/archiva/web/servlet/HttpRepositoryContext.java Wed Feb 11 06:11:40 2009 @@ -0,0 +1,161 @@ +package org.apache.archiva.web.servlet; + +/* + * 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. + */ + +import org.apache.archiva.repository.api.PathUtils; +import org.apache.archiva.repository.api.MimeTypes; +import org.apache.archiva.repository.api.RepositoryContext; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.archiva.repository.api.RequestType; +import org.apache.commons.codec.binary.Base64; + +public class HttpRepositoryContext implements RepositoryContext +{ + private static final MimeTypes mimeTypes = new MimeTypes(); + + private HttpServletRequest request; + private HttpServletResponse response; + + private final String logicalPath; + private final String principal; + private final String repositoryId; + private final RequestType requestType; + private int contentLength; + + public HttpRepositoryContext(HttpServletRequest request, HttpServletResponse response) + { + this.request = request; + this.response = response; + + this.repositoryId = PathUtils.getRepositoryId(request.getPathInfo()); + this.logicalPath = PathUtils.getLogicalPath(request.getPathInfo()); + + if (request.getAuthType() != null && !HttpServletRequest.BASIC_AUTH.equals(request.getAuthType())) + { + throw new RuntimeException("Authentication type " + request.getAuthType() + " is not supported"); + } + + this.principal = getPrincipal(request); + + if ("PUT".equals(request.getMethod())) + { + this.requestType = RequestType.Write; + } + else + { + this.requestType = RequestType.Read; + } + } + + private static String getPrincipal(HttpServletRequest request) + { + String header = request.getHeader( "Authorization" ); + + // in tomcat this is : authorization=Basic YWRtaW46TWFuYWdlMDc= + if ( header == null ) + { + header = request.getHeader( "authorization" ); + } + + if ( ( header != null ) && header.startsWith( "Basic " ) ) + { + String base64Token = header.substring( 6 ); + String token = new String( Base64.decodeBase64( base64Token.getBytes() ) ); + + String username = ""; + int delim = token.indexOf( ':' ); + + if ( delim != ( -1 ) ) + { + username = token.substring( 0, delim ); + } + return username; + } + return null; + } + + public String getLogicalPath() + { + return logicalPath; + } + + public String getPrincipal() + { + return principal; + } + + public String getRepositoryId() + { + return repositoryId; + } + + public RequestType getRequestType() + { + return requestType; + } + + public InputStream getInputStream() + { + try + { + return request.getInputStream(); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + public OutputStream getOutputStream() + { + try + { + //Head should not return a body + if ("HEAD".equals(request.getMethod())) + { + return null; + } + return response.getOutputStream(); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + public int getContentLength() + { + return contentLength; + } + + public void setContentLength(int contentLength) + { + this.contentLength = contentLength; + } + + public String getContentType() + { + return mimeTypes.getMimeType(logicalPath); + } +} Added: archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/src/main/java/org/apache/archiva/web/servlet/IndexWriter.java URL: http://svn.apache.org/viewvc/archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/src/main/java/org/apache/archiva/web/servlet/IndexWriter.java?rev=743242&view=auto ============================================================================== --- archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/src/main/java/org/apache/archiva/web/servlet/IndexWriter.java (added) +++ archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/src/main/java/org/apache/archiva/web/servlet/IndexWriter.java Wed Feb 11 06:11:40 2009 @@ -0,0 +1,117 @@ +package org.apache.archiva.web.servlet; + +/* + * 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. + */ + +import org.apache.archiva.repository.api.ResourceContext; +import org.apache.archiva.repository.api.Status; +import org.apache.commons.lang.StringUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.io.PrintWriter; +import java.io.File; +import java.io.IOException; +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.apache.archiva.repository.api.ResourceType; +import org.apache.commons.io.output.ByteArrayOutputStream; + +public final class IndexWriter +{ + public static void write(List<Status> resources, ResourceContext context, HttpServletResponse resp, boolean writeContent) throws IOException + { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintWriter writer = new PrintWriter(outputStream, true); + + resp.setDateHeader("last-modified", new Date().getTime()); + resp.setContentType("text/html"); + writeDocumentStart(context, writer); + writeHyperlinks(resources, context, writer); + writeDocumentEnd(writer); + + resp.setContentLength(outputStream.toByteArray().length); + if (writeContent) + { + resp.getOutputStream().write(outputStream.toByteArray()); + } + } + + private static void writeDocumentStart(ResourceContext context, PrintWriter writer) + { + writer.println("<html>"); + writer.println("<head>"); + writer.println("<title>Collection: " + context.getLogicalPath() + "</title>"); + writer.println("</head>"); + writer.println("<body>"); + writer.println("<h3>Collection: " + context.getLogicalPath() + "</h3>"); + + //Check if not root + if (!"/".equals(context.getLogicalPath())) + { + File file = new File(context.getLogicalPath()); + String parentName = file.getParent().equals("") ? "/" : file.getParent(); + + //convert to unix path in case archiva is hosted on windows + parentName = StringUtils.replace(parentName, "\\", "/" ); + + writer.println("<ul>"); + writer.println("<li><a href=\"../\">" + parentName + "</a> <i><small>(Parent)</small></i></li>"); + writer.println("</ul>"); + } + + writer.println("<ul>"); + } + + private static void writeDocumentEnd(PrintWriter writer) + { + writer.println("</ul>"); + writer.println("</body>"); + writer.println("</html>"); + } + + private static void writeHyperlinks(List<Status> resources, ResourceContext context, PrintWriter writer) + { + ArrayList<Status> sortedResources = new ArrayList<Status>(resources); + sortedResources.remove(0); //First entry is the stat for the collection itself + Collections.sort(sortedResources, new Status.StatusNameComparator()); + + for( Status status : sortedResources) + { + //Ignore hidden directories + if (!status.getName().startsWith(".")) + { + writeHyperlink(writer, status); + } + } + } + + private static void writeHyperlink(PrintWriter writer, Status status ) + { + if (ResourceType.Collection.equals(status.getResourceType())) + { + writer.println("<li><a href=\"" + status.getName() + "/\">" + status.getName() + "</a></li>"); + } + else + { + writer.println("<li><a href=\"" + status.getName() + "\">" + status.getName() + "</a></li>"); + } + } +} \ No newline at end of file Added: archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/src/main/java/org/apache/archiva/web/servlet/RepositoryServlet.java URL: http://svn.apache.org/viewvc/archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/src/main/java/org/apache/archiva/web/servlet/RepositoryServlet.java?rev=743242&view=auto ============================================================================== --- archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/src/main/java/org/apache/archiva/web/servlet/RepositoryServlet.java (added) +++ archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-repository-servlet/src/main/java/org/apache/archiva/web/servlet/RepositoryServlet.java Wed Feb 11 06:11:40 2009 @@ -0,0 +1,190 @@ +package org.apache.archiva.web.servlet; + +/* + * 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. + */ + +import org.apache.archiva.repository.api.RepositoryContext; +import org.apache.archiva.repository.api.RepositoryManager; +import org.apache.archiva.repository.api.RepositoryManagerFactory; +import org.apache.archiva.repository.api.ResourceContext; +import org.apache.archiva.repository.api.Status; +import org.apache.archiva.repository.api.interceptor.PostRepositoryInterceptor; +import org.apache.archiva.repository.api.interceptor.PreRepositoryInterceptor; +import org.apache.archiva.repository.api.interceptor.RepositoryInterceptorFactory; +import java.io.IOException; +import java.util.Date; +import java.util.List; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.archiva.repository.api.ResourceType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RepositoryServlet extends HttpServlet +{ + private static final Logger log = LoggerFactory.getLogger(RepositoryServlet.class); + + private final RepositoryInterceptorFactory<PreRepositoryInterceptor> preRepositoryInterceptorFactory; + + private final RepositoryInterceptorFactory<PostRepositoryInterceptor> postRepositoryInterceptorFactory; + + private final RepositoryManagerFactory repositoryManagerFactory; + + private static final String MKCOL_METHOD = "MKCOL"; + + private static final String LAST_MODIFIED = "last-modified"; + + public RepositoryServlet( RepositoryInterceptorFactory<PreRepositoryInterceptor> preRepositoryInterceptorFactory, + RepositoryInterceptorFactory<PostRepositoryInterceptor> postRepositoryInterceptorFactory, + RepositoryManagerFactory repositoryManagerFactory) + { + this.preRepositoryInterceptorFactory = preRepositoryInterceptorFactory; + this.postRepositoryInterceptorFactory = postRepositoryInterceptorFactory; + this.repositoryManagerFactory = repositoryManagerFactory; + } + + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + resp.setHeader("Server", "Apache Archiva"); + resp.setDateHeader("Date", new Date().getTime()); + + //Backwards compatability with the weddav wagon + if (MKCOL_METHOD.equals(req.getMethod())) + { + resp.setStatus(HttpServletResponse.SC_CREATED); + return; + } + super.service(req, resp); + } + + @Override + protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + handleRequest(req, resp); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + handleRequest(req, resp); + } + + @Override + protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + handleRequest(req, resp); + } + + private void handleRequest(final HttpServletRequest req, final HttpServletResponse resp) + throws IOException + { + log.debug("Request started"); + HttpRepositoryContext context = new HttpRepositoryContext(req, resp); + log.debug("Running PreRepositoryInterceptors"); + executePreRepositoryInterceptors(context); + log.debug("Executing Repository Manager"); + runRepositoryManager(context, req, resp); + log.debug("Running PostRepositoryInterceptors"); + executePostRepositoryInterceptors(context); + log.debug("Request Completed"); + } + + private void executePreRepositoryInterceptors(RepositoryContext context) + { + for (final PreRepositoryInterceptor interceptor : preRepositoryInterceptorFactory.getRepositoryInterceptors()) + { + interceptor.intercept(context); + } + } + + private void executePostRepositoryInterceptors(RepositoryContext context) + { + for (final PostRepositoryInterceptor interceptor : postRepositoryInterceptorFactory.getRepositoryInterceptors()) + { + interceptor.intercept(context); + } + } + + private void runRepositoryManager(final RepositoryContext context, final HttpServletRequest req, final HttpServletResponse resp) + throws IOException + { + for (final RepositoryManager manager : repositoryManagerFactory.getRepositoryManagers()) + { + final ResourceContext resourceContext = manager.handles(context); + if (resourceContext != null) + { + log.debug("Request handled by " + manager.toString()); + doContent(manager, resourceContext, req, resp); + break; + } + } + } + + private void doContent(final RepositoryManager repositoryManager, final ResourceContext context, final HttpServletRequest req, final HttpServletResponse resp) + throws IOException + { + if ("PUT".equals(req.getMethod())) + { + repositoryManager.write(context, req.getInputStream()); + return; + } + + final List<Status> results = repositoryManager.stat(context); + + if (!results.isEmpty()) + { + final boolean withBody = !"HEAD".equals(req.getMethod()); + final Status status = results.get(0); + if (ResourceType.Collection.equals(status.getResourceType())) + { + //If does not end with slash we should redirect + if (!req.getRequestURI().endsWith("/" )) + { + resp.sendRedirect(req.getRequestURI() + "/"); + return; + } + + Status collectionStatus = results.get(0); + resp.setDateHeader(LAST_MODIFIED, collectionStatus.getLastModified()); + resp.setStatus(HttpServletResponse.SC_OK); + + IndexWriter.write(results, context, resp, withBody); + } + else + { + resp.setStatus(HttpServletResponse.SC_OK); + resp.setContentLength((int)status.getContentLength()); + resp.setContentType(status.getContentType()); + resp.setDateHeader(LAST_MODIFIED, status.getLastModified()); + + if (withBody) + { + repositoryManager.read(context, resp.getOutputStream()); + } + } + } + else + { + resp.sendError(HttpServletResponse.SC_NOT_FOUND); + } + } +} Modified: archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-webapp/pom.xml URL: http://svn.apache.org/viewvc/archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-webapp/pom.xml?rev=743242&r1=743241&r2=743242&view=diff ============================================================================== --- archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-webapp/pom.xml (original) +++ archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/archiva-webapp/pom.xml Wed Feb 11 06:11:40 2009 @@ -180,6 +180,10 @@ <artifactId>archiva-webdav</artifactId> </dependency> <dependency> + <groupId>org.apache.archiva</groupId> + <artifactId>archiva-repository-servlet</artifactId> + </dependency> + <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-spring-plugin</artifactId> <scope>runtime</scope> Modified: archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/pom.xml URL: http://svn.apache.org/viewvc/archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/pom.xml?rev=743242&r1=743241&r2=743242&view=diff ============================================================================== --- archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/pom.xml (original) +++ archiva/branches/archiva-with-new-repoapi/archiva-modules/archiva-web/pom.xml Wed Feb 11 06:11:40 2009 @@ -13,9 +13,7 @@ ~ 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. - --> - -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + --><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.apache.archiva</groupId> @@ -35,6 +33,7 @@ <module>archiva-webdav</module> <module>archiva-rss</module> <module>archiva-xmlrpc</module> + <module>archiva-repository-servlet</module> </modules> <profiles> @@ -45,4 +44,4 @@ </modules> </profile> </profiles> -</project> +</project> \ No newline at end of file Modified: archiva/branches/archiva-with-new-repoapi/pom.xml URL: http://svn.apache.org/viewvc/archiva/branches/archiva-with-new-repoapi/pom.xml?rev=743242&r1=743241&r2=743242&view=diff ============================================================================== --- archiva/branches/archiva-with-new-repoapi/pom.xml (original) +++ archiva/branches/archiva-with-new-repoapi/pom.xml Wed Feb 11 06:11:40 2009 @@ -403,6 +403,16 @@ </dependency> <dependency> <groupId>org.apache.archiva</groupId> + <artifactId>archiva-repository-api</artifactId> + <version>1.2-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.archiva</groupId> + <artifactId>archiva-repository</artifactId> + <version>1.2-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.archiva</groupId> <artifactId>archiva-docs</artifactId> <version>1.2-SNAPSHOT</version> <type>zip</type> @@ -421,6 +431,11 @@ </dependency> <dependency> <groupId>org.apache.archiva</groupId> + <artifactId>archiva-repository-servlet</artifactId> + <version>1.2-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.archiva</groupId> <artifactId>archiva-webdav</artifactId> <version>1.2-SNAPSHOT</version> </dependency> @@ -468,7 +483,7 @@ <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> - <version>3.2</version> + <version>3.2.1</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> @@ -483,7 +498,7 @@ <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> - <version>2.2</version> + <version>2.4</version> </dependency> <dependency> <groupId>org.apache.derby</groupId>
