diff --git a/pom.xml b/pom.xml index 9722a75970..38bb6a6d38 100644 --- a/pom.xml +++ b/pom.xml @@ -161,7 +161,6 @@ <scope>provided</scope> </dependency> - <!-- JPA --> <!-- Hibernate impl --> <dependency> @@ -321,6 +320,11 @@ <artifactId>wicket-components</artifactId> <version>1.0-SNAPSHOT</version> </dependency> + <dependency> + <groupId>com.sun.jersey</groupId> + <artifactId>jersey-client</artifactId> + <version>1.10</version> + </dependency> </dependencies> @@ -471,6 +475,7 @@ <org.springframework.version>3.0.5.RELEASE</org.springframework.version> <org.springframework.data.version>1.0.3.RELEASE</org.springframework.data.version> <querydsl.version>2.3.3</querydsl.version> + <remote.lookup.url>https://api.dsv.su.se/rest</remote.lookup.url> </properties> <profiles> @@ -494,6 +499,7 @@ <database.showSql>true</database.showSql> <database.generateDdl>true</database.generateDdl> <wicket.mode>deployment</wicket.mode> + <remote.lookup.url>http://apitest.dsv.su.se:8080/rest</remote.lookup.url> </properties> </profile> <profile> @@ -505,6 +511,7 @@ <database.showSql>false</database.showSql> <database.generateDdl>false</database.generateDdl> <wicket.mode>deployment</wicket.mode> + <remote.lookup.url>https://api.dsv.su.se/rest</remote.lookup.url> </properties> </profile> </profiles> diff --git a/src/main/java/se/su/dsv/scipro/admin/panels/ManualImportExportPanel.java b/src/main/java/se/su/dsv/scipro/admin/panels/ManualImportExportPanel.java index b947e7686f..70b48ae02d 100644 --- a/src/main/java/se/su/dsv/scipro/admin/panels/ManualImportExportPanel.java +++ b/src/main/java/se/su/dsv/scipro/admin/panels/ManualImportExportPanel.java @@ -1,10 +1,8 @@ /** - * + * */ package se.su.dsv.scipro.admin.panels; -import java.io.Serializable; - import org.apache.log4j.Logger; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.CheckBox; @@ -13,16 +11,16 @@ import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.CompoundPropertyModel; import org.apache.wicket.spring.injection.annot.SpringBean; -import org.springframework.context.annotation.ImportResource; - import se.su.dsv.scipro.ApplicationSettings; import se.su.dsv.scipro.io.ExternalImporter; import se.su.dsv.scipro.io.exceptions.ExternalImportException; import se.su.dsv.scipro.security.auth.roles.Roles; +import java.io.Serializable; + public class ManualImportExportPanel extends Panel { private static final long serialVersionUID = 1L; - private Label statusMessage = new Label("statusMessage",""); + private Label statusMessage = new Label("statusMessage", ""); @SpringBean private ExternalImporter externalImporter; @SpringBean @@ -31,25 +29,30 @@ public class ManualImportExportPanel extends Panel { private ApplicationSettings applicationSettings; private Form<ImportExportParams> importExportForm; private static final Logger logger = Logger.getLogger(ManualImportExportPanel.class); - + public ManualImportExportPanel(String id) { super(id); init(); } - private void init(){ + + private void init() { statusMessage.setOutputMarkupId(true); - if(hasRemote()) - setMessage("Using remote: "+getRemoteUrl()); - else + if (hasRemote()) { + setMessage("Using remote: " + getRemoteUrl()); + } + else { setMessage("No remote configured"); + } add(statusMessage); setupForm(); } - private void setupForm(){ - importExportForm = new Form<ImportExportParams>("importExportForm",new CompoundPropertyModel<ImportExportParams>(new ImportExportParams())){ + + private void setupForm() { + importExportForm = new Form<ImportExportParams>("importExportForm", new CompoundPropertyModel<ImportExportParams>(new ImportExportParams())) { private static final long serialVersionUID = 1L; + @Override - public void onSubmit(){ + public void onSubmit() { final ImportExportParams params = getModelObject(); final String userNameIn = params.getImportUserName(); final long userIdIn = params.getImportUserId(); @@ -60,78 +63,85 @@ public class ManualImportExportPanel extends Panel { final String projectTitleIn = params.getImportProjectTitle(); final long projectIdOut = params.getExportProjectId(); - if(userNameIn != null && !userNameIn.equals("")){ - logger.debug("Attempting remote import of user: "+userNameIn); - try{ - externalImporter.importUser(userNameIn,params.isIncludeLinkedProjects()); - setMessage("Succesfully imported user with username: "+userNameIn + " from "+getRemoteUrl()); - }catch(final ExternalImportException eie){ - logger.warn("Caught error while importing user from remote system: "+eie.getMessage()); - setMessage("Failed to import user with username: "+userNameIn+ " from "+getRemoteUrl()+", error: "+eie.getWrappedErrorCode()); + if (userNameIn != null && !userNameIn.equals("")) { + logger.debug("Attempting remote import of user: " + userNameIn); + try { + externalImporter.importUser(userNameIn, params.isIncludeLinkedProjects()); + setMessage("Succesfully imported user with username: " + userNameIn + " from " + getRemoteUrl()); + } + catch (final ExternalImportException eie) { + logger.warn("Caught error while importing user from remote system: " + eie.getMessage()); + setMessage("Failed to import user with username: " + userNameIn + " from " + getRemoteUrl() + ", error: " + eie.getWrappedErrorCode()); } } - if(userIdIn > 0){ - logger.debug("Attempting remote import of id: "+userIdIn); - try{ - externalImporter.importUser(userIdIn,params.isIncludeLinkedProjects()); - setMessage("Succesfully imported user with id: "+userIdIn + " from "+getRemoteUrl()); - }catch(final ExternalImportException eie){ - logger.warn("Caught error while importing user from remote system: "+eie.getMessage()); - setMessage("Failed to import user with id: "+userIdIn+ " from "+getRemoteUrl()+", error: "+eie.getWrappedErrorCode()); + if (userIdIn > 0) { + logger.debug("Attempting remote import of id: " + userIdIn); + try { + externalImporter.importUser(userIdIn, params.isIncludeLinkedProjects()); + setMessage("Succesfully imported user with id: " + userIdIn + " from " + getRemoteUrl()); + } + catch (final ExternalImportException eie) { + logger.warn("Caught error while importing user from remote system: " + eie.getMessage()); + setMessage("Failed to import user with id: " + userIdIn + " from " + getRemoteUrl() + ", error: " + eie.getWrappedErrorCode()); } } - if(importSupervisors){ + if (importSupervisors) { logger.debug("Importing all listed supervisors"); - try{ - externalImporter.importUsersOfRole(Roles.EMPLOYEE,params.isIncludeLinkedProjects()); + try { + externalImporter.importUsersOfRole(Roles.EMPLOYEE, params.isIncludeLinkedProjects()); setMessage("Successfully imported supervisors from " + getRemoteUrl()); - }catch(final ExternalImportException eie){ - logger.warn("Caught error while importing supervisors from remote system: "+eie.getMessage()); - setMessage("Failed to import supervisors from "+getRemoteUrl()+", error: "+eie.getWrappedErrorCode()); + } + catch (final ExternalImportException eie) { + logger.warn("Caught error while importing supervisors from remote system: " + eie.getMessage()); + setMessage("Failed to import supervisors from " + getRemoteUrl() + ", error: " + eie.getWrappedErrorCode()); } } - if(importSupervisorUnits){ + if (importSupervisorUnits) { logger.debug("Importing attached units for supervisors"); try { externalImporter.importSupervisorUnits(); setMessage("Successfully imported attached units to supervisors from " + getRemoteUrl()); - } catch (final ExternalImportException eie) { - logger.warn("Caught error while importing units to supervisors from remote system: "+eie.getMessage()); - setMessage("Failed to import units from "+getRemoteUrl()+", error: "+eie.getWrappedErrorCode()); + } + catch (final ExternalImportException eie) { + logger.warn("Caught error while importing units to supervisors from remote system: " + eie.getMessage()); + setMessage("Failed to import units from " + getRemoteUrl() + ", error: " + eie.getWrappedErrorCode()); } } - if(importResearchAreas){ + if (importResearchAreas) { logger.debug("Importing all research areas from remote host"); try { externalImporter.importResearchAreas(); setMessage("Successfully imported research areas from " + getRemoteUrl()); - } catch (final ExternalImportException eie){ - logger.warn("Caught error while importing research areas from remote system: "+eie.getMessage()); - setMessage("Failed to import research areas from "+getRemoteUrl()+", error: "+eie.getWrappedErrorCode()); + } + catch (final ExternalImportException eie) { + logger.warn("Caught error while importing research areas from remote system: " + eie.getMessage()); + setMessage("Failed to import research areas from " + getRemoteUrl() + ", error: " + eie.getWrappedErrorCode()); } } - if(projectIdIn > 0){ - logger.debug("Attempting remote import of project: "+projectIdIn); - try{ + if (projectIdIn > 0) { + logger.debug("Attempting remote import of project: " + projectIdIn); + try { externalImporter.importProject(projectIdIn); - setMessage("Successfully imported project with id "+projectIdIn+" from " + getRemoteUrl()); - }catch (final ExternalImportException eie){ - logger.warn("Caught error while importing project from remote system: "+eie.getMessage()); - setMessage("Failed to import project with id "+projectIdIn+" from "+getRemoteUrl()+", error: "+eie.getWrappedErrorCode()); + setMessage("Successfully imported project with id " + projectIdIn + " from " + getRemoteUrl()); + } + catch (final ExternalImportException eie) { + logger.warn("Caught error while importing project from remote system: " + eie.getMessage()); + setMessage("Failed to import project with id " + projectIdIn + " from " + getRemoteUrl() + ", error: " + eie.getWrappedErrorCode()); } } - if(projectTitleIn != null && !projectTitleIn.equals((""))){ - logger.debug("Attempting remote import of projects matching: '"+projectTitleIn+"'"); - try{ + if (projectTitleIn != null && !projectTitleIn.equals((""))) { + logger.debug("Attempting remote import of projects matching: '" + projectTitleIn + "'"); + try { externalImporter.importProjects(projectTitleIn); - setMessage("Successfully imported all projects matching title '"+projectTitleIn+"' from " + getRemoteUrl()); - }catch (final ExternalImportException eie){ - logger.warn("Caught error while importing project from remote system: "+eie.getMessage()); - setMessage("Failed to import projects matching title '"+projectTitleIn+"' from "+getRemoteUrl()+", error: "+eie.getWrappedErrorCode()); + setMessage("Successfully imported all projects matching title '" + projectTitleIn + "' from " + getRemoteUrl()); + } + catch (final ExternalImportException eie) { + logger.warn("Caught error while importing project from remote system: " + eie.getMessage()); + setMessage("Failed to import projects matching title '" + projectTitleIn + "' from " + getRemoteUrl() + ", error: " + eie.getWrappedErrorCode()); } } - if(projectIdOut > 0){ - logger.debug("Attempting remote export of project: "+projectIdOut); + if (projectIdOut > 0) { + logger.debug("Attempting remote export of project: " + projectIdOut); throw new UnsupportedOperationException("Not implemented yet"); } } @@ -148,17 +158,21 @@ public class ManualImportExportPanel extends Panel { importExportForm.add(new CheckBox("importResearchAreas")); importExportForm.setVisible(hasRemote()); } - private boolean hasRemote(){ + + private boolean hasRemote() { return externalImporter.supportsRemoteOperations(); } - private String getRemoteUrl(){ - return applicationSettings.getRemoteLookupUrl(); + + private String getRemoteUrl() { + return externalImporter.getLookupUrl(); } - private void setMessage(final String message){ + + private void setMessage(final String message) { statusMessage.setDefaultModelObject(message); } + //Utility model-class - private class ImportExportParams implements Serializable{ + private class ImportExportParams implements Serializable { private static final long serialVersionUID = 5961088002006031317L; private String importUserName; private long importUserId; @@ -168,58 +182,76 @@ public class ManualImportExportPanel extends Panel { private long importProjectId; private String importProjectTitle; private long exportProjectId; - private boolean includeLinkedProjects=false; + private boolean includeLinkedProjects = false; + public String getImportUserName() { return importUserName; } + public void setImportUserName(String importUserName) { this.importUserName = importUserName; } + public long getImportProjectId() { return importProjectId; } + public void setImportProjectId(long importProjectId) { this.importProjectId = importProjectId; } + public String getImportProjectTitle() { return importProjectTitle; } + public void setImportProjectTitle(String importProjectTitle) { this.importProjectTitle = importProjectTitle; } + public long getExportProjectId() { return exportProjectId; } + public void setExportProjectId(long exportProjectId) { this.exportProjectId = exportProjectId; } + public boolean isImportSupervisors() { return importSupervisors; } + public void setImportSupervisors(boolean importSupervisors) { this.importSupervisors = importSupervisors; } + public boolean isImportSupervisorUnits() { return importSupervisorUnits; } + public void setImportSupervisorUnits(boolean importSupervisorUnits) { this.importSupervisorUnits = importSupervisorUnits; } + public long getImportUserId() { return importUserId; } + public void setImportUserId(long importUserId) { this.importUserId = importUserId; } + public boolean isIncludeLinkedProjects() { return includeLinkedProjects; } + public void setIncludeLinkedProjects(boolean includeLinkedProjects) { this.includeLinkedProjects = includeLinkedProjects; } + public void setImportResearchAreas(boolean importResearchAreas) { this.importResearchAreas = importResearchAreas; } + public boolean isImportResearchAreas() { return importResearchAreas; } diff --git a/src/main/java/se/su/dsv/scipro/io/ExternalImporter.java b/src/main/java/se/su/dsv/scipro/io/ExternalImporter.java index 21abfae753..d93bc7fb07 100644 --- a/src/main/java/se/su/dsv/scipro/io/ExternalImporter.java +++ b/src/main/java/se/su/dsv/scipro/io/ExternalImporter.java @@ -7,12 +7,21 @@ import se.su.dsv.scipro.security.auth.roles.Roles; * Specifies interaction of an importing service component. */ public interface ExternalImporter { + String getLookupUrl(); + void importUser(final String userName, boolean includeLinkedEntities) throws ExternalImportException; + void importUser(final long externalIdentifier, boolean includeLinkedEntities) throws ExternalImportException; - void importUsersOfRole(final Roles role,boolean includeLinkedEntities) throws ExternalImportException; + + void importUsersOfRole(final Roles role, boolean includeLinkedEntities) throws ExternalImportException; + void importProject(final long externalIdentifier) throws ExternalImportException; + void importProjects(final String matchingTitle) throws ExternalImportException; + void importSupervisorUnits() throws ExternalImportException; + void importResearchAreas() throws ExternalImportException; + boolean supportsRemoteOperations(); } diff --git a/src/main/java/se/su/dsv/scipro/io/http/ApiClient.java b/src/main/java/se/su/dsv/scipro/io/http/ApiClient.java new file mode 100644 index 0000000000..ae6e92f825 --- /dev/null +++ b/src/main/java/se/su/dsv/scipro/io/http/ApiClient.java @@ -0,0 +1,79 @@ +package se.su.dsv.scipro.io.http; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.UniformInterfaceException; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; +import org.apache.log4j.Logger; +import se.su.dsv.scipro.io.exceptions.HttpRemoteRespondedWithFailureException; + +import javax.ws.rs.core.MediaType; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class ApiClient { + public static final int CONN_TIMEOUT = 1000 * 60; + public static final int READ_TIMEOUT = 1000 * 120; + public static final String ENC_TYPE = "UTF8"; + + + public enum REQUEST_TYPE {POST, GET} + + + private final Logger logger = Logger.getLogger(ApiClient.class); + private final Map<String, String> parameters = new HashMap<String, String>(); + private String baseUrl; + private String user; + private String password; + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } + + public String getBaseUrl() { + return baseUrl; + } + + private ApiClient() { + } + + public void setUser(String user) { + this.user = user; + } + + public void setPassword(String password) { + this.password = password; + } + + /** + * Start to process the request + * + * @throws IOException if a connection error occurred + */ + public void processRequest(String urlPath, DtoResponseHandler responseHandler, Map<String, String> parameters, REQUEST_TYPE requestType) throws HttpRemoteRespondedWithFailureException { + logger.debug("Sending remote request (" + requestType + "): " + urlPath + "?" + parameters); + try { + WebResource resource = new Client().resource(baseUrl + urlPath); + resource.addFilter(new HTTPBasicAuthFilter(user, password)); + + String result = null; + + switch (requestType) { + case GET: + for (Map.Entry<String, String> stringStringEntry : parameters.entrySet()) { + resource = resource.queryParam(stringStringEntry.getKey(), stringStringEntry.getValue()); + } + result = resource.accept(MediaType.APPLICATION_JSON_TYPE).get(String.class); + break; + case POST: + result = resource.entity(parameters).accept(MediaType.APPLICATION_JSON).post(String.class); + } + responseHandler.handleResponse(result); + } + catch (UniformInterfaceException e) { + logger.error(e.getMessage(), e); + throw new HttpRemoteRespondedWithFailureException(e.getResponse().getStatus()); + } + } +} \ No newline at end of file diff --git a/src/main/java/se/su/dsv/scipro/io/http/HttpRequestSender.java b/src/main/java/se/su/dsv/scipro/io/http/HttpRequestSender.java deleted file mode 100644 index 30d9e6b184..0000000000 --- a/src/main/java/se/su/dsv/scipro/io/http/HttpRequestSender.java +++ /dev/null @@ -1,152 +0,0 @@ - package se.su.dsv.scipro.io.http; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.SocketTimeoutException; -import java.net.URL; -import java.net.UnknownHostException; -import java.util.HashMap; -import java.util.Map; - -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; - -import se.su.dsv.scipro.io.exceptions.HttpRemoteRespondedWithFailureException; - -public class HttpRequestSender { - public static final int CONN_TIMEOUT = 1000*60; - public static final int READ_TIMEOUT = 1000*120; - public static final String ENC_TYPE = "UTF8"; - - public enum REQUEST_TYPE{POST,GET}; - - private final REQUEST_TYPE requestType; - private final Logger logger = Logger.getLogger(HttpRequestSender.class); - private final DtoResponseHandler responseHandler; - private final Map<String, String> parameters = new HashMap<String,String>(); - private final String url; - private final String user; - private final String password; - - public HttpRequestSender(final DtoResponseHandler responseHandler, final String url, final String user, final String password, final Map<String, String> parameters, final REQUEST_TYPE requestType){ - if(responseHandler == null){ - logger.error("Could not send request, no response handler was provided"); - throw new IllegalArgumentException("You need to provide a handler for the response"); - } - if(url == null){ - logger.error("Can't create request for null url"); - throw new IllegalArgumentException("url parameter must be non-null"); - } - this.responseHandler = responseHandler; - this.url = url; - this.user = user; - this.password = password; - if(parameters!=null) - this.parameters.putAll(parameters); - this.requestType = requestType; - } - /** - * Start to process the request - * @throws IOException if a connection error occurred - */ - public void processRequest() throws IOException, HttpRemoteRespondedWithFailureException { - logger.debug("Sending remote request ("+requestType+"): " + url + "?"+parameters); - String parameterData = ""; - int count = 0; - //Format request - for(Map.Entry<String, String> me : parameters.entrySet()){ - if(count > 0){ - parameterData += "&"; - } - parameterData += me.getKey() + "=" + me.getValue(); - count++; - } - //Add to request as appropriate - String urlString = url; - if(requestType == REQUEST_TYPE.GET && parameters.size() > 0){ - urlString += "?" + parameterData; - } - - HttpURLConnection conn = null; - OutputStreamWriter osr = null; - BufferedReader br = null; - try{ - //This will throw an MalformedURLException if the url is not valid - URL u = new URL(urlString); - conn = (HttpURLConnection) getConnection(u); - conn.setRequestMethod(requestType.name()); - //Set connection timeouts - conn.setConnectTimeout(CONN_TIMEOUT); - conn.setReadTimeout(READ_TIMEOUT); - if(user != null && password != null) - conn.setRequestProperty("Authorization", getBasicEncodedAuthData()); - conn.setRequestProperty("Accept", getAcceptContentType()); - //Handle POST-style requests - if(requestType == REQUEST_TYPE.POST){ - conn.setDoOutput(true); - osr = new OutputStreamWriter(conn.getOutputStream()); - osr.write(parameterData); - osr.flush(); - } - //Handle response errors early on - if(conn.getResponseCode() != HttpServletResponse.SC_OK){ - logger.error("Request URL: "+ u + " responded with failure, status code: " + conn.getResponseCode()); - dispatchError(conn.getResponseCode()); - } - br = new BufferedReader(new InputStreamReader(conn.getInputStream(),ENC_TYPE)); - String line = ""; - StringBuffer response = new StringBuffer(); - while((line = br.readLine()) != null){ - response.append(line); - } - responseHandler.handleResponse(response.toString()); - }catch(final MalformedURLException mue){ - logger.warn("Malformed url: " + urlString + " caused exception"); - throw mue; - }catch(final SocketTimeoutException ste){ - logger.warn("Socket timeout while talking to remote host on URL: " + urlString); - throw ste; - }catch(final UnknownHostException uhe){ - logger.warn("Unknown host: " + urlString + " caused exception"); - throw uhe; - }finally{ - if(conn != null){ - conn.disconnect(); - } - if(osr != null){ - try{ - osr.close(); - }catch(final IOException ioe){ - logger.warn("Close on output stream caused an exception, not much to do about that"); - } - } - if(br != null){ - try{ - br.close(); - }catch(final IOException ioe){ - logger.warn("Close on input stream caused an exception, not much to do about that"); - } - } - } - } - private void dispatchError(int responseCode) { - throw new HttpRemoteRespondedWithFailureException(responseCode); - } - private String getBasicEncodedAuthData() { - String userpassword = user + ":" + password; - String encodedAuthorization = Base64.encodeBase64String(userpassword.getBytes()); - return ("Basic "+encodedAuthorization); - } - private String getAcceptContentType() { - return "application/json"; - } - protected HttpURLConnection getConnection(final URL url) throws IOException{ - return (HttpURLConnection)url.openConnection(); - } -} diff --git a/src/main/java/se/su/dsv/scipro/io/http/HttpsRequestSender.java b/src/main/java/se/su/dsv/scipro/io/http/HttpsRequestSender.java deleted file mode 100644 index 3a39105c80..0000000000 --- a/src/main/java/se/su/dsv/scipro/io/http/HttpsRequestSender.java +++ /dev/null @@ -1,24 +0,0 @@ - package se.su.dsv.scipro.io.http; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.Map; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSession; - -import org.apache.log4j.Logger; - -public class HttpsRequestSender extends HttpRequestSender{ - private Logger logger = Logger.getLogger(HttpsRequestSender.class); - public HttpsRequestSender(final DtoResponseHandler responseHandler, final String url, final String user, final String password, final Map<String, String> parameters, final REQUEST_TYPE requestType){ - super(responseHandler,url,user,password,parameters,requestType); - } - @Override - protected HttpURLConnection getConnection(final URL url) throws IOException{ - HttpsURLConnection con = (HttpsURLConnection)url.openConnection(); - return con; - } -} diff --git a/src/main/java/se/su/dsv/scipro/io/impl/ExternalImporterDaisyImpl.java b/src/main/java/se/su/dsv/scipro/io/impl/ExternalImporterDaisyImpl.java index 40722f4d89..813494655f 100644 --- a/src/main/java/se/su/dsv/scipro/io/impl/ExternalImporterDaisyImpl.java +++ b/src/main/java/se/su/dsv/scipro/io/impl/ExternalImporterDaisyImpl.java @@ -1,44 +1,25 @@ package se.su.dsv.scipro.io.impl; -import java.io.IOException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; - import se.su.dsv.scipro.ApplicationSettings; import se.su.dsv.scipro.data.dao.interfaces.ProjectDao; import se.su.dsv.scipro.data.dao.interfaces.UserDao; import se.su.dsv.scipro.data.dataobjects.Project; import se.su.dsv.scipro.data.dataobjects.User; import se.su.dsv.scipro.io.ExternalImporter; -import se.su.dsv.scipro.io.dto.AbstractDtoResponseHandler; -import se.su.dsv.scipro.io.dto.ProjectDTO; -import se.su.dsv.scipro.io.dto.ProjectDTOCollectionWrapper; -import se.su.dsv.scipro.io.dto.ProjectParticipantDTO; -import se.su.dsv.scipro.io.dto.ProjectParticipantDTOCollectionWrapper; -import se.su.dsv.scipro.io.dto.ResearchAreaDTO; -import se.su.dsv.scipro.io.dto.ResearchAreaDTOCollectionWrapper; -import se.su.dsv.scipro.io.dto.PersonDTO; -import se.su.dsv.scipro.io.dto.PersonDTOCollectionWrapper; -import se.su.dsv.scipro.io.dto.UnitDTO; -import se.su.dsv.scipro.io.dto.UnitDTOCollectionWrapper; -import se.su.dsv.scipro.io.dto.UserDTO; -import se.su.dsv.scipro.io.dto.UserDTOCollectionWrapper; -import se.su.dsv.scipro.io.dto.UserRoleDTO; -import se.su.dsv.scipro.io.dto.UsernameDTO; -import se.su.dsv.scipro.io.dto.UsernameDTOCollectionWrapper; +import se.su.dsv.scipro.io.dto.*; import se.su.dsv.scipro.io.exceptions.ExternalImportException; -import se.su.dsv.scipro.io.exceptions.HttpRemoteRespondedWithFailureException; import se.su.dsv.scipro.io.facade.ImporterFacade; -import se.su.dsv.scipro.io.http.HttpRequestSender; -import se.su.dsv.scipro.io.http.HttpsRequestSender; +import se.su.dsv.scipro.io.http.ApiClient; import se.su.dsv.scipro.security.auth.roles.Roles; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + /** * Importer implementation, uses standard HTTP requests and Json-wrappers. * To use this class as the importer, configure it via applicationContext.xml. @@ -53,355 +34,383 @@ public class ExternalImporterDaisyImpl implements ExternalImporter { @Autowired private ProjectDao projectDao; private final Logger logger = Logger.getLogger(ExternalImporterDaisyImpl.class); + + private ApiClient client; + + public void setClient(ApiClient client) { + this.client = client; + } + + public ApiClient getClient() { + return client; + } + + @Override + public String getLookupUrl() { + return client.getBaseUrl(); + } + @Override @Transactional - public void importUser(final String userName, boolean includeLinkedEntities) throws ExternalImportException{ - final Map<String,String> parameters = new HashMap<String,String>(); + public void importUser(final String userName, boolean includeLinkedEntities) throws ExternalImportException { + final Map<String, String> parameters = new HashMap<String, String>(); final UserDTOPreProcessor userDTODecorator = getDefaultUserProcessor(includeLinkedEntities); //parameters.put("showTheses", Boolean.valueOf(includeLinkedEntities).toString()); - sendDefaultUserRequest(parameters,HttpRequestSender.REQUEST_TYPE.GET,userDTODecorator,new UrlProcessor(){ + sendDefaultUserRequest(parameters, ApiClient.REQUEST_TYPE.GET, userDTODecorator, new UrlProcessor() { @Override - String process(final String url){ - return (url+"/person/username/"+userName); + String process(final String url) { + return (url + "/person/username/" + userName); } }); } @Override @Transactional - public void importUser(final long externalIdentifier, boolean includeLinkedEntities) throws ExternalImportException{ - final Map<String,String> parameters = new HashMap<String,String>(); + public void importUser(final long externalIdentifier, boolean includeLinkedEntities) throws ExternalImportException { + final Map<String, String> parameters = new HashMap<String, String>(); final UserDTOPreProcessor userDTODecorator = getDefaultUserProcessor(includeLinkedEntities); - sendDefaultUserRequest(parameters,HttpRequestSender.REQUEST_TYPE.GET,userDTODecorator,new UrlProcessor(){ + sendDefaultUserRequest(parameters, ApiClient.REQUEST_TYPE.GET, userDTODecorator, new UrlProcessor() { @Override - String process(final String url){ - return (url+"/person/"+externalIdentifier); + String process(final String url) { + return (url + "/person/" + externalIdentifier); } }); } + @Override @Transactional - public void importUsersOfRole(final Roles role, boolean includeLinkedEntities) throws ExternalImportException{ - final Map<String,String> parameters = new HashMap<String,String>(); + public void importUsersOfRole(final Roles role, boolean includeLinkedEntities) throws ExternalImportException { + final Map<String, String> parameters = new HashMap<String, String>(); final UserDTOPreProcessor employeeDTODecorator = getDefaultEmployeeUserProcessor(includeLinkedEntities);//Force all returned users to be assigned the local "Supervisor" role - if(!role.equals(Roles.EMPLOYEE)) //Only supports employees currently + if (!role.equals(Roles.EMPLOYEE)) //Only supports employees currently + { throw new UnsupportedOperationException("Sorry, only the EMPLOYEE role is currently supported"); - sendDefaultUserRequest(parameters,HttpRequestSender.REQUEST_TYPE.GET, employeeDTODecorator,new UrlProcessor(){ + } + sendDefaultUserRequest(parameters, ApiClient.REQUEST_TYPE.GET, employeeDTODecorator, new UrlProcessor() { @Override - String process(final String url){ - return (url+"/orgunit/4/supervisors");//Hehe + String process(final String url) { + return (url + "/orgunit/4/supervisors");//Hehe } }); } + @Override public void importProjects(final String title) throws ExternalImportException { - final Map<String,String> parameters = new HashMap<String,String>(); + final Map<String, String> parameters = new HashMap<String, String>(); parameters.put("title", title); - Set<ProjectDTO> externalProjectSet = fetchRemoteProjects(parameters,HttpRequestSender.REQUEST_TYPE.GET,null, new UrlProcessor(){ + Set<ProjectDTO> externalProjectSet = fetchRemoteProjects(parameters, ApiClient.REQUEST_TYPE.GET, new UrlProcessor() { @Override - String process(final String url){ - return (url+"/thesis"); + String process(final String url) { + return (url + "/thesis"); } }); final Set<ProjectDTO> projectsWithParticipants = projectDTOWithParticipants(externalProjectSet); - for(ProjectDTO projectDTO : projectsWithParticipants){ + for (ProjectDTO projectDTO : projectsWithParticipants) { final Project project = projectDao.getProjectByIdentifier(projectDTO.id); - if(project == null) - logger.info("Importing new project: '" + projectDTO+"'"); - else - logger.info("Updating existing project: '" + projectDTO+"'"); + if (project == null) { + logger.info("Importing new project: '" + projectDTO + "'"); + } + else { + logger.info("Updating existing project: '" + projectDTO + "'"); + } importerFacade.mergeProject(project, projectDTO); } } + @Override public void importProject(final long externalIdentifier) throws ExternalImportException { - Set<ProjectDTO> externalProjectSet = fetchRemoteProjects(new HashMap<String,String>(),HttpRequestSender.REQUEST_TYPE.GET,null, new UrlProcessor(){ + Set<ProjectDTO> externalProjectSet = fetchRemoteProjects(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() { @Override - String process(final String url){ - return (url+"/thesis/"+externalIdentifier); + String process(final String url) { + return (url + "/thesis/" + externalIdentifier); } }); final Set<ProjectDTO> projectsWithParticipants = projectDTOWithParticipants(externalProjectSet); - for(ProjectDTO projectDTO : projectsWithParticipants){ + for (ProjectDTO projectDTO : projectsWithParticipants) { final Project project = projectDao.getProjectByIdentifier(projectDTO.id); - if(project == null) - logger.info("Importing new project: '" + projectDTO+"'"); - else - logger.info("Updating existing project: '" + projectDTO+"'"); + if (project == null) { + logger.info("Importing new project: '" + projectDTO + "'"); + } + else { + logger.info("Updating existing project: '" + projectDTO + "'"); + } importerFacade.mergeProject(project, projectDTO); } } - + @Override @Transactional public void importSupervisorUnits() throws ExternalImportException { - Set<UnitDTO> unitSet = fetchRemoteUnits(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor() { + Set<UnitDTO> unitSet = fetchRemoteUnits(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() { @Override - String process(final String url){ - return (url+"/orgunit/4/subunits"); + String process(final String url) { + return (url + "/orgunit/4/subunits"); } }); - + importerFacade.addUnexistingUnitsAsKeywords(unitSet); Set<PersonDTO> allSupervisorsOnUnits = new HashSet<PersonDTO>(); - for (final UnitDTO unitDTO : unitSet){ - Set<PersonDTO> supervisorSet = fetchSupervisorsOnUnit(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor() { + for (final UnitDTO unitDTO : unitSet) { + Set<PersonDTO> supervisorSet = fetchSupervisorsOnUnit(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() { @Override - String process(final String url){ - return (url+"/orgunit/"+unitDTO.id+"/supervisors"); + String process(final String url) { + return (url + "/orgunit/" + unitDTO.id + "/supervisors"); } }); allSupervisorsOnUnits.addAll(supervisorSet); - if(!supervisorSet.isEmpty()){ + if (!supervisorSet.isEmpty()) { for (PersonDTO supervisorDTO : supervisorSet) { - importerFacade.addUnitToSupervisor(supervisorDTO, unitDTO); - } - } else - logger.info("Unit: " + unitDTO.name + " has no supervisors attached."); + importerFacade.addUnitToSupervisor(supervisorDTO, unitDTO); + } + } + else { + logger.info("Unit: " + unitDTO.name + " has no supervisors attached."); + } } - + // Compare the list of supervisors with remote units with the list of // all supervisors in scipro, to make sure to remove units from the // users that doesn't have one in daisy. logger.debug("Number of supervisors on remote units: " + allSupervisorsOnUnits.size()); importerFacade.removeUnitFromSupervisorsNotInSet(allSupervisorsOnUnits); } - + @Override @Transactional public void importResearchAreas() throws ExternalImportException { - Set<ResearchAreaDTO> areaSet = fetchResearchAreas(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor() { + Set<ResearchAreaDTO> areaSet = fetchResearchAreas(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() { @Override - String process(final String url){ - return (url+"/orgunit/4/researchAreas"); + String process(final String url) { + return (url + "/orgunit/4/researchAreas"); } }); logger.info("Received " + areaSet.size() + " research areas from remote and adding those who not exist to database"); - if(!areaSet.isEmpty()){ + if (!areaSet.isEmpty()) { importerFacade.addUnexistingResearchAreas(areaSet); - } + } } - - private Set<PersonDTO> fetchSupervisorsOnUnit(final Map<String, String> parameters, final HttpRequestSender.REQUEST_TYPE requestType, UrlProcessor urlProcessor) { - final String requestUrl = (urlProcessor==null?getRequestUrl():urlProcessor.process(getRequestUrl())); + + private Set<PersonDTO> fetchSupervisorsOnUnit(final Map<String, String> parameters, final ApiClient.REQUEST_TYPE requestType, UrlProcessor urlProcessor) { + final String requestUrl = (urlProcessor == null ? getRequestUrl() : urlProcessor.process(getRequestUrl())); final Set<PersonDTO> dtoCache = new HashSet<PersonDTO>(); - final HttpsRequestSender senderProxy = new HttpsRequestSender(new AbstractDtoResponseHandler() { - - @Override - public void handleResponse(String response) { - logger.info("Response received (from: "+ requestUrl+"): " + response); - final PersonDTOCollectionWrapper supervisorCollection = asSupervisorCollection(response); - if(supervisorCollection.size() == 0){ - throw new ExternalImportException("No supervisors found in remote"); - } else { - dtoCache.addAll(supervisorCollection.getPersons()); + try { + client.processRequest(requestUrl, new AbstractDtoResponseHandler() { + + @Override + public void handleResponse(String response) { + logger.info("Response received (from: " + requestUrl + "): " + response); + final PersonDTOCollectionWrapper supervisorCollection = asSupervisorCollection(response); + if (supervisorCollection.size() == 0) { + throw new ExternalImportException("No supervisors found in remote"); + } + else { + dtoCache.addAll(supervisorCollection.getPersons()); + } + logger.info("Received " + supervisorCollection.size() + " supervisor" + (supervisorCollection.size() == 1 ? "" : "s") + " from remote"); } - logger.info("Received " + supervisorCollection.size() + " supervisor"+(supervisorCollection.size()==1?"":"s")+" from remote"); - } - }, requestUrl, getRequestUser(), getRequestPassword(), parameters, requestType); - try{ - process(senderProxy); - } catch (final ExternalImportException eie){ + }, parameters, requestType); + } + catch (final ExternalImportException eie) { logger.warn("No supervisors found"); } return dtoCache; } - - private Set<UnitDTO> fetchRemoteUnits(final Map<String,String> parameters,final HttpRequestSender.REQUEST_TYPE requestType, - UrlProcessor urlProcessor) { - final String requestUrl = (urlProcessor==null?getRequestUrl():urlProcessor.process(getRequestUrl())); + + private Set<UnitDTO> fetchRemoteUnits(final Map<String, String> parameters, final ApiClient.REQUEST_TYPE requestType, + UrlProcessor urlProcessor) { + final String requestUrl = (urlProcessor == null ? getRequestUrl() : urlProcessor.process(getRequestUrl())); final Set<UnitDTO> dtoCache = new HashSet<UnitDTO>(); - final HttpsRequestSender senderProxy = new HttpsRequestSender(new AbstractDtoResponseHandler(){ - @Override - public void handleResponse(String response) { - logger.info("Response received (from: "+requestUrl+"): " + response); - final UnitDTOCollectionWrapper unitCollection = asUnitCollection(response);//The query will always returns a collection, regardless of backing data - if(unitCollection.size() == 0){//If at this point we have nothing, we have to throw. - throw new ExternalImportException("No units found in remote"); - }else{ - dtoCache.addAll(unitCollection.getUnits()); + try { + client.processRequest(requestUrl, new AbstractDtoResponseHandler() { + @Override + public void handleResponse(String response) { + logger.info("Response received (from: " + requestUrl + "): " + response); + final UnitDTOCollectionWrapper unitCollection = asUnitCollection(response);//The query will always returns a collection, regardless of backing data + if (unitCollection.size() == 0) {//If at this point we have nothing, we have to throw. + throw new ExternalImportException("No units found in remote"); + } + else { + dtoCache.addAll(unitCollection.getUnits()); + } + logger.info("Received " + unitCollection.size() + " unit" + (unitCollection.size() == 1 ? "" : "s") + " from remote"); } - logger.info("Received " + unitCollection.size() + " unit"+(unitCollection.size()==1?"":"s")+" from remote"); - } - }, requestUrl, getRequestUser(), getRequestPassword(), parameters, requestType); - try{ - process(senderProxy); - }catch(final ExternalImportException eie){ + }, parameters, requestType); + } + catch (final ExternalImportException eie) { logger.warn("No units found"); } - return dtoCache; + return dtoCache; } @Override public boolean supportsRemoteOperations() { return true; } + /** * Private utility method, sends request and signals failure via exceptions. + * * @param parameters * @param requestType */ - private void sendDefaultUserRequest(final Map<String,String> parameters, final HttpRequestSender.REQUEST_TYPE requestType, final UserDTOPreProcessor preProcessor, final UrlProcessor urlProcessor){ - final String requestUrl = (urlProcessor==null?getRequestUrl():urlProcessor.process(getRequestUrl())); - final HttpsRequestSender senderProxy = new HttpsRequestSender(new AbstractDtoResponseHandler(){ + private void sendDefaultUserRequest(final Map<String, String> parameters, final ApiClient.REQUEST_TYPE requestType, final UserDTOPreProcessor preProcessor, final UrlProcessor urlProcessor) { + final String requestUrl = (urlProcessor == null ? getRequestUrl() : urlProcessor.process(getRequestUrl())); + client.processRequest(requestUrl, new AbstractDtoResponseHandler() { @Override public void handleResponse(String response) { - logger.info("Response recieved (from: "+requestUrl+"): " + response); + logger.info("Response recieved (from: " + requestUrl + "): " + response); final UserDTOCollectionWrapper userCollection = asUserCollectionWrapper(response);//The query will always returns a collection, regardless of backing data - if(userCollection.size() == 0){//If at this point we have nothing, we have to throw. + if (userCollection.size() == 0) {//If at this point we have nothing, we have to throw. throw new ExternalImportException("No users found in remote"); - }else{ - for(final UserDTO userDTO:userCollection){ + } + else { + for (final UserDTO userDTO : userCollection) { final User user = userDao.getUserByIdentifier(userDTO.id); - if(user == null) - logger.info("Importing new user: '" + userDTO+"'"); - else - logger.info("Updating existing user: '" + userDTO+"'"); - importerFacade.mergeUser(user, (preProcessor!=null?preProcessor.process(userDTO):userDTO)); + if (user == null) { + logger.info("Importing new user: '" + userDTO + "'"); + } + else { + logger.info("Updating existing user: '" + userDTO + "'"); + } + importerFacade.mergeUser(user, (preProcessor != null ? preProcessor.process(userDTO) : userDTO)); } } - logger.info("Recieved " + userCollection.size() + " user"+(userCollection.size()==1?"":"s")+" from remote"); + logger.info("Recieved " + userCollection.size() + " user" + (userCollection.size() == 1 ? "" : "s") + " from remote"); } - }, requestUrl, getRequestUser(), getRequestPassword(), parameters, requestType); - process(senderProxy); + }, parameters, requestType); } - private Set<ProjectDTO> fetchRemoteProjects(final Map<String,String> parameters, final HttpRequestSender.REQUEST_TYPE requestType, final ProjectDTOPreProcessor preProcessor, final UrlProcessor urlProcessor){ - final String requestUrl = (urlProcessor==null?getRequestUrl():urlProcessor.process(getRequestUrl())); + + private Set<ProjectDTO> fetchRemoteProjects(final Map<String, String> parameters, final ApiClient.REQUEST_TYPE requestType, final UrlProcessor urlProcessor) { + final String requestUrl = (urlProcessor == null ? getRequestUrl() : urlProcessor.process(getRequestUrl())); final Set<ProjectDTO> dtoCache = new HashSet<ProjectDTO>(); - final HttpsRequestSender senderProxy = new HttpsRequestSender(new AbstractDtoResponseHandler(){ - @Override - public void handleResponse(String response) { - logger.info("Response recieved (from: "+requestUrl+"): " + response); - final ProjectDTOCollectionWrapper projectCollection = asProjectCollection(response);//The query will always returns a collection, regardless of backing data - if(projectCollection.size() == 0){//If at this point we have nothing, we have to throw. - throw new ExternalImportException("No projects found in remote"); - }else{ - dtoCache.addAll(projectCollection.getProjects()); + try { + client.processRequest(requestUrl, new AbstractDtoResponseHandler() { + @Override + public void handleResponse(String response) { + logger.info("Response recieved (from: " + requestUrl + "): " + response); + final ProjectDTOCollectionWrapper projectCollection = asProjectCollection(response);//The query will always returns a collection, regardless of backing data + if (projectCollection.size() == 0) {//If at this point we have nothing, we have to throw. + throw new ExternalImportException("No projects found in remote"); + } + else { + dtoCache.addAll(projectCollection.getProjects()); + } + logger.info("Recieved " + projectCollection.size() + " project" + (projectCollection.size() == 1 ? "" : "s") + " from remote"); } - logger.info("Recieved " + projectCollection.size() + " project"+(projectCollection.size()==1?"":"s")+" from remote"); - } - }, requestUrl, getRequestUser(), getRequestPassword(), parameters, requestType); - try{ - process(senderProxy); - }catch(final ExternalImportException eie){ + }, parameters, requestType); + } + catch (final ExternalImportException eie) { logger.warn("No projects found, this may or may not indicate a problem"); } return dtoCache; } - - private Set<UsernameDTO> fetchRemoteUsernames(final Map<String,String> parameters, final HttpRequestSender.REQUEST_TYPE requestType, final UrlProcessor urlProcessor) { - final String requestUrl = (urlProcessor==null?getRequestUrl():urlProcessor.process(getRequestUrl())); + + private Set<UsernameDTO> fetchRemoteUsernames(final Map<String, String> parameters, final ApiClient.REQUEST_TYPE requestType, final UrlProcessor urlProcessor) { + final String requestUrl = (urlProcessor == null ? getRequestUrl() : urlProcessor.process(getRequestUrl())); final Set<UsernameDTO> dtoCache = new HashSet<UsernameDTO>(); - final HttpsRequestSender senderProxy = new HttpsRequestSender(new AbstractDtoResponseHandler() { - - @Override - public void handleResponse(String response) { - logger.info("Response recieved (from: "+requestUrl+"): " + response); - final UsernameDTOCollectionWrapper usernameCollection = asUsernameCollection(response); - if(usernameCollection.size() == 0){ - throw new ExternalImportException("No usernames found in remote"); - }else{ - dtoCache.addAll(usernameCollection.getUsernames()); + try { + client.processRequest(requestUrl, new AbstractDtoResponseHandler() { + + @Override + public void handleResponse(String response) { + logger.info("Response recieved (from: " + requestUrl + "): " + response); + final UsernameDTOCollectionWrapper usernameCollection = asUsernameCollection(response); + if (usernameCollection.size() == 0) { + throw new ExternalImportException("No usernames found in remote"); + } + else { + dtoCache.addAll(usernameCollection.getUsernames()); + } + logger.info("Received " + usernameCollection.size() + " usernames" + (usernameCollection.size() == 1 ? "" : "s") + " from remote"); } - logger.info("Received " + usernameCollection.size() + " usernames"+(usernameCollection.size()==1?"":"s")+" from remote"); - } - }, requestUrl, getRequestUser(), getRequestPassword(), parameters, requestType); - try{ - process(senderProxy); - } catch (final ExternalImportException eie){ + }, parameters, requestType); + } + catch (final ExternalImportException eie) { logger.warn("No usernames found"); } + return dtoCache; } - - private Set<ResearchAreaDTO> fetchResearchAreas(final Map<String, String> parameters, final HttpRequestSender.REQUEST_TYPE requestType, final UrlProcessor urlProcessor) { - final String requestUrl = (urlProcessor==null?getRequestUrl():urlProcessor.process(getRequestUrl())); + + private Set<ResearchAreaDTO> fetchResearchAreas(final Map<String, String> parameters, final ApiClient.REQUEST_TYPE requestType, final UrlProcessor urlProcessor) { + final String requestUrl = (urlProcessor == null ? getRequestUrl() : urlProcessor.process(getRequestUrl())); final Set<ResearchAreaDTO> dtoCache = new HashSet<ResearchAreaDTO>(); - final HttpsRequestSender senderProxy = new HttpsRequestSender(new AbstractDtoResponseHandler(){ - @Override - public void handleResponse(String response) { - logger.info("Response recieved (from: "+requestUrl+"): " + response); - final ResearchAreaDTOCollectionWrapper areaCollection = asAreaCollection(response);//The query will always returns a collection, regardless of backing data - if(areaCollection.size() == 0){//If at this point we have nothing, we have to throw. - throw new ExternalImportException("No research areas found in remote"); - }else{ - dtoCache.addAll(areaCollection.getAreas()); + try { + client.processRequest(requestUrl, new AbstractDtoResponseHandler() { + @Override + public void handleResponse(String response) { + logger.info("Response recieved (from: " + requestUrl + "): " + response); + final ResearchAreaDTOCollectionWrapper areaCollection = asAreaCollection(response);//The query will always returns a collection, regardless of backing data + if (areaCollection.size() == 0) {//If at this point we have nothing, we have to throw. + throw new ExternalImportException("No research areas found in remote"); + } + else { + dtoCache.addAll(areaCollection.getAreas()); + } + logger.info("Recieved " + areaCollection.size() + " research area" + (areaCollection.size() == 1 ? "" : "s") + " from remote"); } - logger.info("Recieved " + areaCollection.size() + " research area"+(areaCollection.size()==1?"":"s")+" from remote"); - } - }, requestUrl, getRequestUser(), getRequestPassword(), parameters, requestType); - try{ - process(senderProxy); - }catch(final ExternalImportException eie){ + }, parameters, requestType); + } + catch (final ExternalImportException eie) { logger.warn("No research areas found, this may or may not indicate a problem"); } return dtoCache; } - - private Set<ProjectParticipantDTO> fetchParticipants(final Map<String, String> parameters, final HttpRequestSender.REQUEST_TYPE requestType, final UrlProcessor urlProcessor) { - final String requestUrl = (urlProcessor==null?getRequestUrl():urlProcessor.process(getRequestUrl())); + + private Set<ProjectParticipantDTO> fetchParticipants(final Map<String, String> parameters, final ApiClient.REQUEST_TYPE requestType, final UrlProcessor urlProcessor) { + final String requestUrl = (urlProcessor == null ? getRequestUrl() : urlProcessor.process(getRequestUrl())); final Set<ProjectParticipantDTO> dtoCache = new HashSet<ProjectParticipantDTO>(); - final HttpsRequestSender senderProxy = new HttpsRequestSender(new AbstractDtoResponseHandler(){ - @Override - public void handleResponse(String response) { - logger.info("Response recieved (from: "+requestUrl+"): " + response); - final ProjectParticipantDTOCollectionWrapper participantCollection = asParticipantCollection(response);//The query will always returns a collection, regardless of backing data - if(participantCollection.size() == 0){//If at this point we have nothing, we have to throw. - throw new ExternalImportException("No project participants found in remote"); - }else{ - dtoCache.addAll(participantCollection.getParticipants()); + try { + client.processRequest(requestUrl, new AbstractDtoResponseHandler() { + @Override + public void handleResponse(String response) { + logger.info("Response recieved (from: " + requestUrl + "): " + response); + final ProjectParticipantDTOCollectionWrapper participantCollection = asParticipantCollection(response);//The query will always returns a collection, regardless of backing data + if (participantCollection.size() == 0) {//If at this point we have nothing, we have to throw. + throw new ExternalImportException("No project participants found in remote"); + } + else { + dtoCache.addAll(participantCollection.getParticipants()); + } + logger.info("Recieved " + participantCollection.size() + " project participant" + (participantCollection.size() == 1 ? "" : "s") + " from remote"); } - logger.info("Recieved " + participantCollection.size() + " project participant"+(participantCollection.size()==1?"":"s")+" from remote"); - } - }, requestUrl, getRequestUser(), getRequestPassword(), parameters, requestType); - try{ - process(senderProxy); - }catch(final ExternalImportException eie){ + }, parameters, requestType); + } + catch (final ExternalImportException eie) { logger.warn("No project participants found, this may or may not indicate a problem"); } return dtoCache; } - private String getRequestUrl(){ - return applicationSettings.getRemoteLookupUrl(); - } - private String getRequestUser() { - return applicationSettings.getRemoteLookupUser(); - } - private String getRequestPassword() { - return applicationSettings.getRemoteLookupPassword(); - } - private void process(final HttpRequestSender proxy) throws ExternalImportException{ - try{ - proxy.processRequest(); - }catch(final IOException ioe){ - logger.error("A fatal IO exception has occured while contacting remote host at: " + getRequestUrl()); - throw new ExternalImportException(ioe); - }catch(final HttpRemoteRespondedWithFailureException hrrwfe){ - logger.error("Remote host: " + getRequestUrl() + " responded with failure: "+ hrrwfe.getMessage()); - throw new ExternalImportException(hrrwfe);//Use getCause etc to find out the response code and act on it in some meaningful way - } + /** + * @return + * @deprecated Should be removed. This is set in the client config in applicationContext.xml + */ + private String getRequestUrl() { + return ""; } + private UserDTOPreProcessor getDefaultUserProcessor(boolean includeLinkedEntities) { - if(!includeLinkedEntities) + if (!includeLinkedEntities) { return new UserDTOPreProcessor(); - return new UserDTOPreProcessor(){ + } + return new UserDTOPreProcessor() { @Override - UserDTO process(final UserDTO userDTO){ - final Set<ProjectDTO> fetchedProjects = fetchRemoteProjects(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, null, new UrlProcessor(){ + UserDTO process(final UserDTO userDTO) { + final Set<ProjectDTO> fetchedProjects = fetchRemoteProjects(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() { @Override - String process(String url){ - return (url+"/person/"+userDTO.id+"/theses"); + String process(String url) { + return (url + "/person/" + userDTO.id + "/theses"); } }); //Fetch authors and supervisors for each project final Set<ProjectDTO> projectsWithParticipants = projectDTOWithParticipants(fetchedProjects); - final Set<UsernameDTO> fetchedUsernames = fetchRemoteUsernames(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor(){ + final Set<UsernameDTO> fetchedUsernames = fetchRemoteUsernames(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() { @Override - String process(String url){ - return(url+"/person/"+userDTO.id+"/usernames"); + String process(String url) { + return (url + "/person/" + userDTO.id + "/usernames"); } }); userDTO.projects = projectsWithParticipants; @@ -410,88 +419,85 @@ public class ExternalImporterDaisyImpl implements ExternalImporter { } }; } + private UserDTOPreProcessor getDefaultEmployeeUserProcessor(final boolean includeLinkedEntities) { - return new UserDTOPreProcessor(){ + return new UserDTOPreProcessor() { @Override - UserDTO process(final UserDTO userDTO){ - if(includeLinkedEntities){ - final Set<ProjectDTO> fetchedProjects = fetchRemoteProjects(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, null, new UrlProcessor(){ + UserDTO process(final UserDTO userDTO) { + if (includeLinkedEntities) { + final Set<ProjectDTO> fetchedProjects = fetchRemoteProjects(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() { @Override - String process(String url){ - return (url+"/person/"+userDTO.id+"/theses"); + String process(String url) { + return (url + "/person/" + userDTO.id + "/theses"); } }); final Set<ProjectDTO> projectsWithParticipants = projectDTOWithParticipants(fetchedProjects); userDTO.projects = projectsWithParticipants; } - final Set<UsernameDTO> fetchedUsernames = fetchRemoteUsernames(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor(){ + final Set<UsernameDTO> fetchedUsernames = fetchRemoteUsernames(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() { @Override - String process(String url){ - return(url+"/person/"+userDTO.id+"/usernames"); + String process(String url) { + return (url + "/person/" + userDTO.id + "/usernames"); } }); userDTO.usernames = fetchedUsernames; - final Set<ResearchAreaDTO> fetchedResearchAreas = fetchResearchAreas(new HashMap<String,String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor(){ + final Set<ResearchAreaDTO> fetchedResearchAreas = fetchResearchAreas(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() { @Override - String process(String url){ - return (url+"/person/"+userDTO.id+"/researchAreas"); + String process(String url) { + return (url + "/person/" + userDTO.id + "/researchAreas"); } }); userDTO.researchAreas = fetchedResearchAreas; //Force employee role data to be on the DTO UserRoleDTO employeeRole = new UserRoleDTO(); employeeRole.role = UserRoleDTO.EXTERNAL_USER_ROLES.SUPERVISOR_ROLE.asExternal(); - if(!userDTO.roles.contains(employeeRole)){ + if (!userDTO.roles.contains(employeeRole)) { userDTO.roles.add(employeeRole); } return userDTO; } - + }; } - - private Set<ProjectDTO> projectDTOWithParticipants(Set<ProjectDTO> fetchedProjects){ + + private Set<ProjectDTO> projectDTOWithParticipants(Set<ProjectDTO> fetchedProjects) { Set<ProjectDTO> projects = new HashSet<ProjectDTO>(fetchedProjects); for (final ProjectDTO projectDTO : projects) { Set<ProjectParticipantDTO> combinedSet = new HashSet<ProjectParticipantDTO>(); - - final Set<ProjectParticipantDTO> fetchedAuthors = fetchParticipants(new HashMap<String, String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor(){ + + final Set<ProjectParticipantDTO> fetchedAuthors = fetchParticipants(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() { @Override - String process(String url){ - return(url+"/thesis/"+projectDTO.id+"/student"); + String process(String url) { + return (url + "/thesis/" + projectDTO.id + "/student"); } }); combinedSet.addAll(fetchedAuthors); - final Set<ProjectParticipantDTO> fetchedOtherParticipants = fetchParticipants(new HashMap<String, String>(), HttpRequestSender.REQUEST_TYPE.GET, new UrlProcessor(){ + final Set<ProjectParticipantDTO> fetchedOtherParticipants = fetchParticipants(new HashMap<String, String>(), ApiClient.REQUEST_TYPE.GET, new UrlProcessor() { @Override - String process(String url){ - return(url+"/thesis/"+projectDTO.id+"/contributor"); + String process(String url) { + return (url + "/thesis/" + projectDTO.id + "/contributor"); } }); combinedSet.addAll(fetchedOtherParticipants); projectDTO.participants = combinedSet; - + } return projects; } - + /** * Small utility interface/default implementation used to preprocess DTO objects, intended for anonymous inner class-usage. */ - private class UserDTOPreProcessor{ - UserDTO process(UserDTO userDTO){ + private class UserDTOPreProcessor { + UserDTO process(UserDTO userDTO) { return userDTO; } } - private class ProjectDTOPreProcessor{ - ProjectDTO process(ProjectDTO projectDTO){ - return projectDTO; - } - } - private class UrlProcessor{ - String process(String url){ + + private class UrlProcessor { + String process(String url) { return url; } } - + } diff --git a/src/main/java/se/su/dsv/scipro/io/impl/ExternalImporterDefaultImpl.java b/src/main/java/se/su/dsv/scipro/io/impl/ExternalImporterDefaultImpl.java index 2bc7b4b3ff..d846a80788 100644 --- a/src/main/java/se/su/dsv/scipro/io/impl/ExternalImporterDefaultImpl.java +++ b/src/main/java/se/su/dsv/scipro/io/impl/ExternalImporterDefaultImpl.java @@ -1,7 +1,6 @@ package se.su.dsv.scipro.io.impl; import org.apache.log4j.Logger; - import se.su.dsv.scipro.io.ExternalImporter; import se.su.dsv.scipro.io.exceptions.ExternalImportException; import se.su.dsv.scipro.security.auth.roles.Roles; @@ -12,38 +11,51 @@ import se.su.dsv.scipro.security.auth.roles.Roles; */ public class ExternalImporterDefaultImpl implements ExternalImporter { private final Logger logger = Logger.getLogger(ExternalImporterDefaultImpl.class); + + @Override + public String getLookupUrl() { + return "<not specified>"; + } + @Override public void importUser(final String userName, boolean includeLinkedEntities) { - logger.debug("Dummy implementation, the user: "+userName+" will not be imported"); + logger.debug("Dummy implementation, the user: " + userName + " will not be imported"); } + @Override public void importUser(final long externalIdentifier, boolean includeLinkedEntities) { - logger.debug("Dummy implementation, the user with identifier: "+externalIdentifier+" will not be imported"); + logger.debug("Dummy implementation, the user with identifier: " + externalIdentifier + " will not be imported"); } + @Override public void importUsersOfRole(final Roles role, boolean includeLinkedEntities) { logger.debug("Dummy implementation, no users of role: " + role + " will be imported"); } + @Override - public void importProject(long externalIdentifier){ + public void importProject(long externalIdentifier) { logger.debug("Dummy implementation, no project with the id: " + externalIdentifier + " will be imported"); } + @Override public void importProjects(String title) throws ExternalImportException { logger.debug("Dummy implementation, no project matching the title: " + title + " will be imported"); } + @Override public boolean supportsRemoteOperations() { return false; } + @Override public void importSupervisorUnits() throws ExternalImportException { // TODO Auto-generated method stub } + @Override public void importResearchAreas() throws ExternalImportException { // TODO Auto-generated method stub - + } } diff --git a/src/main/resources/applicationContext.xml b/src/main/resources/applicationContext.xml index 0b972bbc05..5a4c578dfe 100644 --- a/src/main/resources/applicationContext.xml +++ b/src/main/resources/applicationContext.xml @@ -12,7 +12,7 @@ http://www.springframework.org/schema/data/jpa/spring-jpa.xsd" default-autowire="byType"> - <jpa:repositories base-package="se.su.dsv.scipro.springdata" /> + <jpa:repositories base-package="se.su.dsv.scipro.springdata"/> <!-- Sets up spring autowire configuration based on annotations --> <context:annotation-config/> @@ -63,13 +63,19 @@ <!-- Load data initializer for default table-data --> <bean class="se.su.dsv.scipro.DataInitialiser" init-method="dataInit"/> <!-- Importer used for remote importing work, use "ExternalImporterDefaultImpl" if you have no remote-import implementation capable of satisfying "ExternalImporter" interface. --> - <bean id="externalImporter" class="se.su.dsv.scipro.io.impl.ExternalImporterDaisyImpl"/> + <bean id="externalImporter" class="se.su.dsv.scipro.io.impl.ExternalImporterDaisyImpl"> + <property name="client" ref="dsvApiClient"/> + </bean> + + <bean id="dsvApiClient" class="se.su.dsv.scipro.io.http.ApiClient"> + <!-- This property points to the location of the remote system used for json requests --> + <property name="baseUrl" value="${remote.lookup.url}"/> + <property name="user" value="thesis"/> + <property name="password" value="dqyhIM8LU5LQ53T3aJNz4SVXeTQ95dLGkN7JlLOv7X7jeTR2NR"/> + </bean> + <!-- Defines global settings for the application --> <bean id="applicationSettings" class="se.su.dsv.scipro.ApplicationSettings"> - <property name="remoteLookupUrl" value="https://api.dsv.su.se/rest"/> - <property name="remoteLookupUser" value="thesis"/> - <property name="remoteLookupPassword" value="dqyhIM8LU5LQ53T3aJNz4SVXeTQ95dLGkN7JlLOv7X7jeTR2NR"/> - <!-- This property points to the location of the remote system used for json requests --> <!-- External auth support (via J2EE standard mechanism REMOTE_USER), if true: other authentication mechanics will be bypassed.--> <property name="acceptExternalAuthentication" value="true"/> </bean>