Bundle-Version: 0.13.1.SNAPSHOT
Web-ContextPath: org.argeo.slc.repo.webapp
Bundle-Vendor: Argeo
-Import-Package: javax.servlet,
+Import-Package: javax.jcr;version="2.0.0",
+ javax.servlet,
javax.servlet.http,
- javax.servlet.resources
+ javax.servlet.resources,
+ org.argeo.security.core,
+ org.argeo.security.jcr,
+ org.argeo.slc.aether.spring,
+ org.argeo.slc.repo.maven.proxy,
+ org.springframework.osgi.web.context.support;version="1.2.1",
+ org.springframework.security;version="2.0.6.RELEASE",
+ org.springframework.security.context;version="2.0.6.RELEASE",
+ org.springframework.security.intercept.web;version="2.0.6.RELEASE",
+ org.springframework.security.providers.anonymous;version="2.0.6.RELEASE",
+ org.springframework.security.ui;version="2.0.6.RELEASE",
+ org.springframework.security.ui.basicauth;version="2.0.6.RELEASE",
+ org.springframework.security.ui.logout;version="2.0.6.RELEASE",
+ org.springframework.security.ui.rememberme;version="2.0.6.RELEASE",
+ org.springframework.security.userdetails;version="2.0.6.RELEASE",
+ org.springframework.security.util;version="2.0.6.RELEASE",
+ org.springframework.security.vote;version="2.0.6.RELEASE",
+ org.springframework.security.wrapper;version="2.0.6.RELEASE",
+ org.springframework.web.context;version="2.5.6.SEC01",
+ org.springframework.web.filter;version="2.5.6.SEC01",
+ org.springframework.web.servlet;version="2.5.6.SEC01",
+ org.springframework.web.servlet.handler;version="2.5.6.SEC01"
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<import resource="osgi.xml" />
+ <import resource="security.xml" />
</beans>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
+ ">
<bean
class="org.springframework.web.servlet.handler.SimpleServletPostProcessor" />
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
- <prop key="*">companyRemoteService</prop>
+ <prop key="*">mavenProxyServlet</prop>
</props>
</property>
</bean>
- <bean id="mavenProxyServlet"
- class="com.somecompany.gwt.server.servicesimpl.CompanyRemoteServiceImpl" />
+ <bean id="mavenProxyService" class="org.argeo.slc.repo.maven.proxy.MavenProxyServiceImpl"
+ init-method="init" destroy-method="destroy">
+ <property name="jcrRepository" ref="jcrRepository" />
+ <property name="defaultRepositories" ref="defaultMavenRepositories" />
+ </bean>
+
+ <bean id="mavenProxyServlet" class="org.argeo.slc.repo.maven.proxy.MavenProxyServlet">
+ <property name="jcrSession" ref="jcrSession" />
+ <property name="proxyService" ref="mavenProxyService" />
+ </bean>
+
+ <bean id="jcrSession" class="org.argeo.security.jcr.SecureThreadBoundSession">
+ <property name="repository" ref="jcrRepository" />
+ <property name="defaultUsername" value="root" />
+ <property name="defaultPassword" value="demo" />
+ </bean>
+
+ <bean
+ class="org.argeo.security.core.AuthenticatedApplicationContextInitialization">
+ <property name="authenticationManager" ref="authenticationManager" />
+ </bean>
+
+ <!-- Remote repositories -->
+ <util:list id="defaultMavenRepositories">
+ <ref local="central" />
+ <ref local="com.springsource.repository.bundles.external" />
+ <ref local="com.springsource.repository.bundles.release" />
+ <ref local="argeo" />
+ <ref local="argeo-snapshots" />
+ </util:list>
+
+ <bean id="central" class="org.argeo.slc.aether.spring.RemoteRepositoryFactory">
+ <property name="url" value="http://repo1.maven.org/maven2" />
+ </bean>
+ <bean id="com.springsource.repository.bundles.release" class="org.argeo.slc.aether.spring.RemoteRepositoryFactory">
+ <property name="url"
+ value="http://repository.springsource.com/maven/bundles/release" />
+ </bean>
+ <bean id="com.springsource.repository.bundles.external" class="org.argeo.slc.aether.spring.RemoteRepositoryFactory">
+ <property name="url"
+ value="http://repository.springsource.com/maven/bundles/external" />
+ </bean>
+ <bean id="argeo" class="org.argeo.slc.aether.spring.RemoteRepositoryFactory">
+ <property name="url" value="http://maven.argeo.org/argeo/" />
+ </bean>
+ <bean id="argeo-snapshots" class="org.argeo.slc.aether.spring.RemoteRepositoryFactory">
+ <property name="url" value="http://dev.argeo.org/maven/argeo-snapshots/" />
+ </bean>
</beans>
\ No newline at end of file
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">\r
\r
- <set id="repositories" interface="javax.jcr.Repository" cardinality="0..N">\r
- <listener ref="repositoryRegister" bind-method="register"\r
- unbind-method="unregister" />\r
- </set>\r
+ <!-- REFRENCES -->\r
+ <!-- Security -->\r
+ <reference id="authenticationManager"\r
+ interface="org.springframework.security.AuthenticationManager" />\r
+ <reference id="userDetailsService"\r
+ interface="org.springframework.security.userdetails.UserDetailsService" />\r
\r
-<!-- <reference id="authenticationManager"-->\r
-<!-- interface="org.springframework.security.AuthenticationManager" />-->\r
+ <!-- JCR -->\r
+ <reference id="jcrRepository" interface="javax.jcr.Repository"\r
+ filter="(argeo.jcr.repository.alias=slc)" />\r
</beans:beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:sec="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">
+
+ <bean id="springSecurityFilterChain" class="org.springframework.security.util.FilterChainProxy">
+ <sec:filter-chain-map path-type="ant">
+ <sec:filter-chain pattern="/**"
+ filters="httpSessionContextIntegrationFilter,logoutFilter,basicProcessingFilter,anonymousProcessingFilter,securityContextHolderAwareRequestFilter,exceptionTranslationFilter,filterInvocationInterceptor" />
+ </sec:filter-chain-map>
+ </bean>
+
+ <!-- The actual authorization checks (called last, but first here for ease
+ of configuration) -->
+ <bean id="filterInvocationInterceptor" parent="filterInvocationInterceptorTemplate">
+ <property name="objectDefinitionSource">
+ <value>
+ CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
+ PATTERN_TYPE_APACHE_ANT
+ /public/**=IS_AUTHENTICATED_ANONYMOUSLY
+ /**=ROLE_USER
+ </value>
+ <!-- <value> -->
+ <!-- CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON -->
+ <!-- PATTERN_TYPE_APACHE_ANT -->
+ <!-- /config/**=ROLE_ADMINISTRATOR -->
+ <!-- /**=IS_AUTHENTICATED_ANONYMOUSLY -->
+ <!-- </value> -->
+ </property>
+ </bean>
+
+ <!-- Integrates the authentication information in the http sessions -->
+ <bean id="httpSessionContextIntegrationFilter"
+ class="org.springframework.security.context.HttpSessionContextIntegrationFilter">
+ <property name="allowSessionCreation" value="true" />
+ </bean>
+
+ <!-- Processes logouts, removing both session informations and the remember-me
+ cookie from the browser -->
+ <bean id="logoutFilter" class="org.springframework.security.ui.logout.LogoutFilter">
+ <constructor-arg value="/web/" />
+ <!-- URL redirected to after logout -->
+ <constructor-arg>
+ <list>
+ <ref bean="rememberMeServices" />
+ <bean
+ class="org.springframework.security.ui.logout.SecurityContextLogoutHandler" />
+ </list>
+ </constructor-arg>
+ </bean>
+
+ <!-- Double check, this may not be necessary -->
+ <bean id="securityContextHolderAwareRequestFilter"
+ class="org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter" />
+
+ <!-- Use the remember me cookie to authenticate -->
+ <bean id="rememberMeProcessingFilter"
+ class="org.springframework.security.ui.rememberme.RememberMeProcessingFilter">
+ <property name="authenticationManager" ref="authenticationManager" />
+ <property name="rememberMeServices" ref="rememberMeServices" />
+ </bean>
+
+ <bean id="rememberMeServices"
+ class="org.springframework.security.ui.rememberme.TokenBasedRememberMeServices">
+ <property name="userDetailsService" ref="userDetailsService" />
+ <property name="key" value="${argeo.security.systemKey}" />
+ </bean>
+
+ <!-- Basic authentication -->
+ <bean id="basicProcessingFilter"
+ class="org.springframework.security.ui.basicauth.BasicProcessingFilter">
+ <property name="authenticationManager">
+ <ref bean="authenticationManager" />
+ </property>
+ <property name="authenticationEntryPoint">
+ <ref local="basicProcessingFilterEntryPoint" />
+ </property>
+ <property name="rememberMeServices" ref="rememberMeServices" />
+ </bean>
+
+ <!-- Activate basic auth when needed -->
+ <bean id="basicProcessingFilterEntryPoint"
+ class="org.springframework.security.ui.basicauth.BasicProcessingFilterEntryPoint">
+ <property name="realmName">
+ <value>Argeo</value>
+ </property>
+ </bean>
+
+ <!-- If everything else failed, anonymous authentication -->
+ <bean id="anonymousProcessingFilter"
+ class="org.springframework.security.providers.anonymous.AnonymousProcessingFilter">
+ <property name="key" value="${argeo.security.systemKey}" />
+ <property name="userAttribute" value="anonymous,ROLE_ANONYMOUS" />
+ </bean>
+
+ <!-- Reacts to security related exceptions -->
+ <bean id="exceptionTranslationFilter"
+ class="org.springframework.security.ui.ExceptionTranslationFilter">
+ <property name="authenticationEntryPoint">
+ <ref bean="basicProcessingFilterEntryPoint" />
+ </property>
+ <property name="accessDeniedHandler">
+ <bean class="org.springframework.security.ui.AccessDeniedHandlerImpl">
+ <property name="errorPage" value="/accessDenied.jsp" />
+ </bean>
+ </property>
+ </bean>
+
+ <!-- Template for authorization checks -->
+ <bean id="filterInvocationInterceptorTemplate" abstract="true"
+ class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
+ <property name="authenticationManager" ref="authenticationManager" />
+ <property name="accessDecisionManager">
+ <bean class="org.springframework.security.vote.AffirmativeBased">
+ <property name="allowIfAllAbstainDecisions" value="false" />
+ <property name="decisionVoters">
+ <list>
+ <bean class="org.springframework.security.vote.RoleVoter" />
+ <bean class="org.springframework.security.vote.AuthenticatedVoter" />
+ </list>
+ </property>
+ </bean>
+ </property>
+ </bean>
+</beans>
\ No newline at end of file
<servlet-name>maven</servlet-name>
<url-pattern>/maven/*</url-pattern>
</servlet-mapping>
+
+ <!-- Security -->
+ <filter>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
</web-app>
--- /dev/null
+package org.argeo.slc.repo.maven.proxy;
+
+/** Synchronizes JCR and Maven repositories */
+public interface MavenProxyService {
+ public String getNodePath(String path);
+
+ public String proxyFile(String path);
+}
--- /dev/null
+package org.argeo.slc.repo.maven.proxy;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.Binary;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.jcr.SlcNames;
+import org.argeo.slc.repo.RepoConstants;
+import org.sonatype.aether.repository.RemoteRepository;
+
+/** Synchronizes the node repository with remote Maven repositories */
+public class MavenProxyServiceImpl implements MavenProxyService, ArgeoNames,
+ SlcNames {
+ private final static Log log = LogFactory
+ .getLog(MavenProxyServiceImpl.class);
+
+ private Repository jcrRepository;
+ private Session jcrAdminSession;
+ private List<RemoteRepository> defaultRepositories = new ArrayList<RemoteRepository>();
+
+ public void init() {
+ try {
+ jcrAdminSession = jcrRepository.login();
+
+ JcrUtils.mkdirs(jcrAdminSession, RepoConstants.ARTIFACTS_BASE_PATH);
+ Node proxiedRepositories = JcrUtils.mkdirs(jcrAdminSession,
+ RepoConstants.PROXIED_REPOSITORIES);
+ for (RemoteRepository repository : defaultRepositories) {
+ if (!proxiedRepositories.hasNode(repository.getId())) {
+ Node proxiedRepository = proxiedRepositories
+ .addNode(repository.getId());
+ proxiedRepository.setProperty(SLC_URL, repository.getUrl());
+ proxiedRepository.setProperty(SLC_TYPE,
+ repository.getContentType());
+ }
+ }
+ jcrAdminSession.save();
+ } catch (RepositoryException e) {
+ JcrUtils.discardQuietly(jcrAdminSession);
+ throw new SlcException("Cannot initialize Maven proxy", e);
+ }
+ }
+
+ public void destroy() {
+ JcrUtils.logoutQuietly(jcrAdminSession);
+ }
+
+ /**
+ * Retrieve and add this file to the repository
+ */
+ public synchronized String proxyFile(String path) {
+ try {
+ Node node = null;
+ proxiedRepositories: for (NodeIterator nit = jcrAdminSession
+ .getNode(RepoConstants.PROXIED_REPOSITORIES).getNodes(); nit
+ .hasNext();) {
+ Node proxiedRepository = nit.nextNode();
+ String repoUrl = proxiedRepository.getProperty(SLC_URL)
+ .getString();
+ String remoteUrl = repoUrl + path;
+ if (log.isTraceEnabled())
+ log.trace("remoteUrl=" + remoteUrl);
+ InputStream in = null;
+ try {
+ URL u = new URL(remoteUrl);
+ in = u.openStream();
+ node = importFile(getNodePath(path), in);
+ if (log.isDebugEnabled())
+ log.debug("Imported " + remoteUrl + " to " + node);
+ break proxiedRepositories;
+ } catch (Exception e) {
+ if (log.isDebugEnabled())
+ log.debug("Cannot read " + remoteUrl + ", skipping... "
+ + e.getMessage());
+ // e.printStackTrace();
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+ }
+
+ if (node != null)
+ return node.getIdentifier();
+ else {
+ log.warn("Could not proxy " + path);
+ return null;
+ }
+ } catch (RepositoryException e) {
+ throw new SlcException("Cannot proxy " + path, e);
+ }
+ }
+
+ /** The JCR path where this file could be found */
+ public String getNodePath(String path) {
+ return RepoConstants.ARTIFACTS_BASE_PATH + path;
+ }
+
+ protected Node importFile(String nodePath, InputStream in) {
+ Binary binary = null;
+ try {
+ Node node = JcrUtils.mkdirs(jcrAdminSession, nodePath,
+ NodeType.NT_FILE, NodeType.NT_FOLDER, false);
+ Node content = node.addNode(Node.JCR_CONTENT, NodeType.NT_RESOURCE);
+ binary = jcrAdminSession.getValueFactory().createBinary(in);
+ content.setProperty(Property.JCR_DATA, binary);
+ jcrAdminSession.save();
+ return node;
+ } catch (RepositoryException e) {
+ JcrUtils.discardQuietly(jcrAdminSession);
+ throw new SlcException("Cannot initialize Maven proxy", e);
+ } finally {
+ JcrUtils.closeQuietly(binary);
+ }
+ }
+
+ public void setJcrRepository(Repository jcrRepository) {
+ this.jcrRepository = jcrRepository;
+ }
+
+ public void setDefaultRepositories(
+ List<RemoteRepository> defaultRepositories) {
+ this.defaultRepositories = defaultRepositories;
+ }
+
+}
import java.io.IOException;
import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
import javax.jcr.Binary;
import javax.jcr.Node;
-import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
-import javax.jcr.nodetype.NodeType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import org.argeo.jcr.JcrUtils;
import org.argeo.slc.SlcException;
import org.argeo.slc.jcr.SlcNames;
-import org.argeo.slc.repo.RepoConstants;
-import org.sonatype.aether.repository.RemoteRepository;
/**
* Expose the SLC repository as a regular Maven repository, proxying third party
private final static Log log = LogFactory.getLog(MavenProxyServlet.class);
+ private MavenProxyService proxyService;
+
private Session jcrSession;
- private List<RemoteRepository> defaultRepositories = new ArrayList<RemoteRepository>();
private String contentTypeCharset = "UTF-8";
- @Override
- public void init() throws ServletException {
- try {
- Node proxiedRepositories = JcrUtils.mkdirs(jcrSession,
- RepoConstants.PROXIED_REPOSITORIES);
- for (RemoteRepository repository : defaultRepositories) {
- if (!proxiedRepositories.hasNode(repository.getId())) {
- Node proxiedRepository = proxiedRepositories
- .addNode(repository.getId());
- proxiedRepository.setProperty(SLC_URL, repository.getUrl());
- proxiedRepository.setProperty(SLC_TYPE,
- repository.getContentType());
- }
- }
- jcrSession.save();
- } catch (RepositoryException e) {
- JcrUtils.discardQuietly(jcrSession);
- throw new SlcException("Cannot initialize Maven proxy", e);
- }
- }
-
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String path = request.getPathInfo();
- String nodePath = RepoConstants.ARTIFACTS_BASE_PATH + path;
- if (log.isDebugEnabled())
- log.debug("path=" + path + ", nodePath=" + nodePath);
+ String nodePath = proxyService.getNodePath(path);
+ if (log.isTraceEnabled())
+ log.trace("path=" + path + ", nodePath=" + nodePath);
try {
- Node node = null;
- if (jcrSession.itemExists(nodePath)) {
- node = jcrSession.getNode(nodePath);
- } else {
- proxiedRepositories: for (NodeIterator nit = jcrSession
- .getNode(RepoConstants.PROXIED_REPOSITORIES).getNodes(); nit
- .hasNext();) {
- Node proxiedRepository = nit.nextNode();
- String repoUrl = proxiedRepository.getProperty(SLC_URL)
- .getString();
- String remoteUrl = repoUrl + path;
- if (log.isDebugEnabled())
- log.debug("remoteUrl=" + remoteUrl);
- InputStream in = null;
- try {
- URL u = new URL(remoteUrl);
- in = u.openStream();
- node = importFile(nodePath, in);
- break proxiedRepositories;
- } catch (Exception e) {
- if (log.isTraceEnabled())
- log.trace("Cannot read " + remoteUrl
- + ", skipping...");
- } finally {
- IOUtils.closeQuietly(in);
- }
- }
-
- if (node == null) {
+ Node node;
+ if (!jcrSession.itemExists(nodePath)) {
+ String nodeIdentifier = proxyService.proxyFile(path);
+ if (nodeIdentifier == null) {
+ //log.warn("Could not proxy " + path);
response.sendError(404);
return;
- // throw new SlcException("Could not find " + path
- // + " among proxies");
+ } else {
+ node = jcrSession.getNodeByIdentifier(nodeIdentifier);
}
+ } else {
+ node = jcrSession.getNode(nodePath);
}
processResponse(nodePath, node, response);
} catch (RepositoryException e) {
throw new SlcException("Cannot proxy " + request, e);
}
- super.doGet(request, response);
+ //super.doGet(request, response);
}
- /** Download the content of the node. */
+ /** Retrieve the content of the node. */
protected void processResponse(String path, Node node,
HttpServletResponse response) {
+ Binary binary = null;
+ InputStream in = null;
try {
String fileName = node.getName();
String ext = FilenameUtils.getExtension(fileName);
response.setHeader("Pragma", "no-cache");
response.setContentType(contentType);
- } catch (RepositoryException e) {
- throw new SlcException("Cannot download " + node, e);
- }
- }
- protected Node importFile(String nodePath, InputStream in) {
- Binary binary = null;
- try {
- Node node = JcrUtils.mkdirs(jcrSession, nodePath, NodeType.NT_FILE,
- NodeType.NT_FOLDER, false);
- Node content = node.addNode(Node.JCR_CONTENT, NodeType.NT_RESOURCE);
- binary = jcrSession.getValueFactory().createBinary(in);
- content.setProperty(Property.JCR_DATA, binary);
- jcrSession.save();
- return node;
- } catch (RepositoryException e) {
- JcrUtils.discardQuietly(jcrSession);
- throw new SlcException("Cannot initialize Maven proxy", e);
+ binary = node.getNode(Property.JCR_CONTENT)
+ .getProperty(Property.JCR_DATA).getBinary();
+ in = binary.getStream();
+ IOUtils.copy(in, response.getOutputStream());
+ } catch (Exception e) {
+ throw new SlcException("Cannot download " + node, e);
} finally {
+ IOUtils.closeQuietly(in);
JcrUtils.closeQuietly(binary);
}
}
+
+ public void setJcrSession(Session jcrSession) {
+ this.jcrSession = jcrSession;
+ }
+
+ public void setProxyService(MavenProxyService proxyService) {
+ this.proxyService = proxyService;
+ }
+
}