[MRM-1490] Expose Archiva services trough REST

start adding some services :
* search
* administration

git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@1159529 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Olivier Lamy 2011-08-19 07:52:52 +00:00
parent 0370ce7a83
commit fd94d9c6ec
12 changed files with 720 additions and 20 deletions

View File

@ -0,0 +1,146 @@
package org.apache.archiva.rest.api.model;
/*
* 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 javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
/**
* @since 1.4
*/
@XmlRootElement( name = "managedRepository" )
public class ManagedRepository
implements Serializable
{
private String id;
private String name;
private String url;
private String layout;
private boolean snapshots = false;
private boolean releases = false;
public ManagedRepository()
{
// no op
}
public ManagedRepository( String id, String name, String url, String layout, boolean snapshots, boolean releases )
{
this.id = id;
this.name = name;
this.url = url;
this.layout = layout;
this.snapshots = snapshots;
this.releases = releases;
}
public boolean equals(Object other)
{
if ( this == other)
{
return true;
}
if ( !(other instanceof ManagedRepository) )
{
return false;
}
ManagedRepository that = (ManagedRepository) other;
boolean result = true;
result = result && ( getId() == null ? that.getId() == null : getId().equals( that.getId() ) );
return result;
}
public String getId()
{
return this.id;
}
public String getLayout()
{
return this.layout;
}
public String getName()
{
return this.name;
}
public String getUrl()
{
return this.url;
}
public int hashCode()
{
int result = 17;
result = 37 * result + ( id != null ? id.hashCode() : 0 );
return result;
}
public boolean isReleases()
{
return this.releases;
}
/**
* Get null
*/
public boolean isSnapshots()
{
return this.snapshots;
}
public void setId(String id)
{
this.id = id;
}
public void setLayout(String layout)
{
this.layout = layout;
}
public void setName(String name)
{
this.name = name;
}
public void setReleases(boolean releases)
{
this.releases = releases;
}
public void setSnapshots(boolean snapshots)
{
this.snapshots = snapshots;
}
public void setUrl(String url)
{
this.url = url;
}
}

View File

@ -0,0 +1,115 @@
package org.apache.archiva.rest.api.model;
/*
* 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 javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
@XmlRootElement( name = "remoteRepository" )
public class RemoteRepository
implements Serializable
{
private String id;
private String name;
private String url;
private String layout;
public RemoteRepository()
{
// no op
}
public RemoteRepository( String id, String name, String url, String layout )
{
this.id = id;
this.name = name;
this.url = url;
this.layout = layout;
}
public boolean equals(Object other)
{
if ( this == other)
{
return true;
}
if ( !(other instanceof RemoteRepository) )
{
return false;
}
RemoteRepository that = (RemoteRepository) other;
boolean result = true;
result = result && ( getId() == null ? that.getId() == null : getId().equals( that.getId() ) );
return result;
}
public String getId()
{
return this.id;
}
public String getLayout()
{
return this.layout;
}
public String getName()
{
return this.name;
}
public String getUrl()
{
return this.url;
}
public int hashCode()
{
int result = 17;
result = 37 * result + ( id != null ? id.hashCode() : 0 );
return result;
}
public void setId(String id)
{
this.id = id;
}
public void setLayout(String layout)
{
this.layout = layout;
}
public void setName(String name)
{
this.name = name;
}
public void setUrl(String url)
{
this.url = url;
}
}

View File

@ -0,0 +1,212 @@
package org.apache.archiva.rest.api.model;
import java.util.ArrayList;
import java.util.List;
/*
* 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.
*/
public class SearchRequest
{
/**
* groupId
*/
private String groupId;
/**
* artifactId
*/
private String artifactId;
/**
* version
*/
private String version;
/**
* packaging (jar, war, pom, etc.)
*/
private String packaging;
/**
* class name or package name
*/
private String className;
/**
* repositories
*/
private List<String> repositories = new ArrayList<String>();
/**
* contains osgi metadata Bundle-Version if available
*
* @since 1.4
*/
private String bundleVersion;
/**
* contains osgi metadata Bundle-SymbolicName if available
*
* @since 1.4
*/
private String bundleSymbolicName;
/**
* contains osgi metadata Export-Package if available
*
* @since 1.4
*/
private String bundleExportPackage;
/**
* contains osgi metadata Export-Service if available
*
* @since 1.4
*/
private String bundleExportService;
public SearchRequest()
{
// no op
}
public SearchRequest( String groupId, String artifactId, String version, String packaging, String className,
List<String> repositories )
{
this.groupId = groupId;
this.artifactId = artifactId;
this.version = version;
this.packaging = packaging;
this.className = className;
this.repositories = repositories;
}
public String getGroupId()
{
return groupId;
}
public void setGroupId( String groupId )
{
this.groupId = groupId;
}
public String getArtifactId()
{
return artifactId;
}
public void setArtifactId( String artifactId )
{
this.artifactId = artifactId;
}
public String getVersion()
{
return version;
}
public void setVersion( String version )
{
this.version = version;
}
public String getPackaging()
{
return packaging;
}
public void setPackaging( String packaging )
{
this.packaging = packaging;
}
public String getClassName()
{
return className;
}
public void setClassName( String className )
{
this.className = className;
}
public List<String> getRepositories()
{
return repositories;
}
public void setRepositories( List<String> repositories )
{
this.repositories = repositories;
}
public String getBundleVersion()
{
return bundleVersion;
}
public void setBundleVersion( String bundleVersion )
{
this.bundleVersion = bundleVersion;
}
public String getBundleSymbolicName()
{
return bundleSymbolicName;
}
public void setBundleSymbolicName( String bundleSymbolicName )
{
this.bundleSymbolicName = bundleSymbolicName;
}
public String getBundleExportPackage()
{
return bundleExportPackage;
}
public void setBundleExportPackage( String bundleExportPackage )
{
this.bundleExportPackage = bundleExportPackage;
}
public String getBundleExportService()
{
return bundleExportService;
}
public void setBundleExportService( String bundleExportService )
{
this.bundleExportService = bundleExportService;
}
@Override
public String toString()
{
return "SearchFields{" + "groupId='" + groupId + '\'' + ", artifactId='" + artifactId + '\'' + ", version='"
+ version + '\'' + ", packaging='" + packaging + '\'' + ", className='" + className + '\''
+ ", repositories=" + repositories + ", bundleVersion='" + bundleVersion + '\'' + ", bundleSymbolicName='"
+ bundleSymbolicName + '\'' + ", bundleExportPackage='" + bundleExportPackage + '\''
+ ", bundleExportService='" + bundleExportService + '\'' + '}';
}
}

View File

@ -35,14 +35,24 @@ public interface PingService
{ {
/** /**
*
* ping service to monitor Archiva with a nice returned message :-) * ping service to monitor Archiva with a nice returned message :-)
*
* @return Yeah Baby It rocks! * @return Yeah Baby It rocks!
*/ */
@Path( "addAuthenticationKey" ) @Path( "ping" )
@GET @GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } ) @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( noRestriction = true ) @RedbackAuthorization( noRestriction = true )
String ping( ); String ping();
/**
* same as #ping but check authz
* @return
*/
@Path( "pingWithAuthz" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( noRestriction = false, noPermission = true )
String pingWithAuthz();
} }

View File

@ -0,0 +1,58 @@
package org.apache.archiva.rest.api.services;
/*
* 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.rest.api.model.ManagedRepository;
import org.apache.archiva.rest.api.model.RemoteRepository;
import org.codehaus.plexus.redback.authorization.RedbackAuthorization;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.List;
/**
* @author Olivier Lamy
* @since 1.4
*/
@Path( "/repositoriesService/" )
public interface RepositoriesService
{
@Path( "getManagedRepositories" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( noRestriction = true )
List<ManagedRepository> getManagedRepositories();
@Path( "getRemoteRepositories" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( noRestriction = true )
List<RemoteRepository> getRemoteRepositories();
@Path( "scanRepository" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( noRestriction = true )
Boolean scanRepository( @QueryParam( "repositoryId" ) String repositoryId,
@QueryParam( "fullScan" ) boolean fullScan );
}

View File

@ -0,0 +1,63 @@
package org.apache.archiva.rest.api.services;
/*
* 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.rest.api.model.Artifact;
import org.apache.archiva.rest.api.model.Dependency;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.Date;
import java.util.List;
@XmlRootElement( name = "searchRequest" )
public interface SearchService
{
/*
* quick/general text search which returns a list of artifacts
* query for an artifact based on a checksum
* query for all available versions of an artifact, sorted in version significance order
* query for all available versions of an artifact since a given date
* query for an artifact's direct dependencies
* query for an artifact's dependency tree (as with mvn dependency:tree - no duplicates should be included)
* query for all artifacts that depend on a given artifact
*/
List<Artifact> quickSearch( String queryString )
throws Exception;
List<Artifact> getArtifactByChecksum( String checksum )
throws Exception;
List<Artifact> getArtifactVersions( String groupId, String artifactId )
throws Exception;
List<Artifact> getArtifactVersionsByDate( String groupId, String artifactId, String version, Date whenGathered )
throws Exception;
List<Dependency> getDependencies( String groupId, String artifactId, String version )
throws Exception;
List<Artifact> getDependencyTree( String groupId, String artifactId, String version )
throws Exception;
List<Artifact> getDependees( String groupId, String artifactId, String version )
throws Exception;
}

View File

@ -34,4 +34,9 @@ public class DefaultPingService
{ {
return "Yeah Baby It rocks!"; return "Yeah Baby It rocks!";
} }
public String pingWithAuthz()
{
return ping();
}
} }

View File

@ -0,0 +1,32 @@
package org.apache.archiva.rest.services;
import org.apache.archiva.rest.api.model.ManagedRepository;
import org.apache.archiva.rest.api.model.RemoteRepository;
import org.apache.archiva.rest.api.services.RepositoriesService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author Olivier Lamy
* @since 1.4
*/
@Service("repositoriesService#rest")
public class DefaultRepositoriesService
implements RepositoriesService
{
public List<ManagedRepository> getManagedRepositories()
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public List<RemoteRepository> getRemoteRepositories()
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public Boolean scanRepository( String repositoryId, boolean fullScan )
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
}

View File

@ -47,6 +47,7 @@
<jaxrs:providers> <jaxrs:providers>
<ref bean="authenticationInterceptor#rest"/> <ref bean="authenticationInterceptor#rest"/>
<ref bean="permissionInterceptor#rest"/> <ref bean="permissionInterceptor#rest"/>
<ref bean="repositoriesService#rest"/>
</jaxrs:providers> </jaxrs:providers>
</jaxrs:server> </jaxrs:server>

View File

@ -21,9 +21,9 @@ package org.apache.archiva.rest.services;
import org.apache.archiva.rest.api.services.PingService; import org.apache.archiva.rest.api.services.PingService;
import org.apache.cxf.jaxrs.client.JAXRSClientFactory; import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
import org.apache.cxf.jaxrs.client.ServerWebApplicationException;
import org.apache.cxf.jaxrs.client.WebClient;
import org.codehaus.redback.rest.services.AbstractRestServicesTest; import org.codehaus.redback.rest.services.AbstractRestServicesTest;
import org.codehaus.redback.rest.services.FakeCreateAdminService;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
/** /**
@ -34,20 +34,6 @@ public class PingServiceTest
extends AbstractRestServicesTest extends AbstractRestServicesTest
{ {
@Before
public void setUp()
throws Exception
{
super.startServer();
FakeCreateAdminService fakeCreateAdminService =
JAXRSClientFactory.create( "http://localhost:" + port + "/services/fakeCreateAdminService/",
FakeCreateAdminService.class );
Boolean res = fakeCreateAdminService.createAdminIfNeeded();
assertTrue( res.booleanValue() );
}
PingService getPingService() PingService getPingService()
{ {
return JAXRSClientFactory.create( "http://localhost:" + port + "/services/archivaServices/", return JAXRSClientFactory.create( "http://localhost:" + port + "/services/archivaServices/",
@ -66,4 +52,32 @@ public class PingServiceTest
String res = getPingService().ping(); String res = getPingService().ping();
assertEquals( "Yeah Baby It rocks!", res ); assertEquals( "Yeah Baby It rocks!", res );
} }
@Test( expected = ServerWebApplicationException.class )
public void pingWithAuthzFailed()
throws Exception
{
try
{
String res = getPingService().pingWithAuthz();
fail( "not in exception" );
}
catch ( ServerWebApplicationException e )
{
assertEquals( 403, e.getStatus() );
throw e;
}
}
@Test
public void pingWithAuthz()
throws Exception
{
PingService service = getPingService();
WebClient.client( service ).header( "Authorization", authorizationHeader );
String res = service.pingWithAuthz();
assertEquals( "Yeah Baby It rocks!", res );
}
} }

View File

@ -0,0 +1,45 @@
package org.apache.archiva.rest.services;
/*
* 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.rest.api.services.RepositoriesService;
import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
import org.codehaus.redback.rest.services.AbstractRestServicesTest;
import org.junit.Test;
/**
* @author Olivier Lamy
*/
public class RepositoriesServiceTest
extends AbstractRestServicesTest
{
RepositoriesService getPingService()
{
return JAXRSClientFactory.create( "http://localhost:" + port + "/services/archivaServices/",
RepositoriesService.class );
}
@Test
public void listRemoteRepositories() throws Exception
{
}
}

View File

@ -275,7 +275,6 @@ public class AdministrationServiceImpl
RepositoryTask task = new RepositoryTask(); RepositoryTask task = new RepositoryTask();
task.setRepositoryId( repoId ); task.setRepositoryId( repoId );
repositoryTaskScheduler.queueTask( task ); repositoryTaskScheduler.queueTask( task );
return true; return true;