Java tutorial
/* * Copyright 2013 Global Biodiversity Information Facility (GBIF) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.gbif.registry.metasync.protocols; import org.gbif.api.model.registry.Contact; import org.gbif.api.vocabulary.Language; import org.gbif.registry.metasync.api.ErrorCode; import org.gbif.registry.metasync.api.MetadataException; import org.gbif.registry.metasync.api.MetadataProtocolHandler; import org.gbif.registry.metasync.util.converter.DateTimeConverter; import org.gbif.registry.metasync.util.converter.LanguageConverter; import org.gbif.registry.metasync.util.converter.PeriodConverter; import org.gbif.registry.metasync.util.converter.UriConverter; import java.io.IOException; import java.net.URI; import java.util.List; import com.google.common.collect.Lists; import org.apache.commons.beanutils.ConvertUtils; import org.apache.commons.digester3.Digester; import org.apache.commons.digester3.annotations.FromAnnotationsRuleModule; import org.apache.commons.digester3.binder.DigesterLoader; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.util.EntityUtils; import org.joda.time.DateTime; import org.joda.time.Period; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; import static org.apache.commons.digester3.binder.DigesterLoader.newLoader; /** * This class is used as a base for all protocols and provides common methods to be used by all protocols. */ public abstract class BaseProtocolHandler implements MetadataProtocolHandler { private static final Logger LOG = LoggerFactory.getLogger(BaseProtocolHandler.class); private final HttpClient httpClient; protected BaseProtocolHandler(HttpClient httpClient) { this.httpClient = httpClient; } /** * Takes two collections of {@link Contact}s and tries to match the {@code newContacts} to the * {@code existingContacts} and returns all Contacts that could <b>not</b> be matched (i.e. those are new Contacts * that did * not previously exist). * * @return new Contacts that do not exist in the existing Contacts already */ protected List<Contact> matchContacts(Iterable<Contact> existingContacts, Iterable<Contact> newContacts) { List<Contact> resultList = Lists.newArrayList(); for (Contact newContact : newContacts) { boolean found = false; for (Contact existingContact : existingContacts) { if (existingContact.lenientEquals(newContact)) { resultList.add(existingContact); found = true; break; } } if (!found) { resultList.add(newContact); } } return resultList; } /** * Makes a HTTP request to the provided {@link URI} and uses the {@link Digester} to parse the response. * * @param uri to issue request against * @param digester to parse response with * @param <T> type of Object to return * @throws MetadataException in case anything goes wrong during the request, all underlying HTTP errors are mapped to * the appropriate {@link ErrorCode}s. */ protected <T> T doHttpRequest(URI uri, Digester digester) throws MetadataException { HttpUriRequest get = new HttpGet(uri); HttpResponse response; try { // Not using a Response Handler here because that can't throw arbitrary Exceptions response = httpClient.execute(get); } catch (ClientProtocolException e) { throw new MetadataException(e, ErrorCode.HTTP_ERROR); } catch (IOException e) { throw new MetadataException(e, ErrorCode.IO_EXCEPTION); } // Everything but HTTP status 200 is an error if (response.getStatusLine().getStatusCode() != 200) { LOG.debug("Received HTTP code[{}] cause[{}] for request: {}", response.getStatusLine().getStatusCode(), response.getStatusLine().getReasonPhrase(), uri); String cause = String.format("Received HTTP code[%d], phrase[%s]", response.getStatusLine().getStatusCode(), response.getStatusLine().getReasonPhrase()); throw new MetadataException(cause, ErrorCode.HTTP_ERROR); } try { return digester.parse(response.getEntity().getContent()); } catch (SAXException e) { throw new MetadataException(e, ErrorCode.PROTOCOL_ERROR); } catch (IOException e) { throw new MetadataException(e, ErrorCode.IO_EXCEPTION); } finally { try { EntityUtils.consume(response.getEntity()); } catch (IOException e2) { LOG.warn("Error consuming content after an exception", e2); } } } /** * Returns a new Digester which is configured with the annotation rules from the passed in class. */ protected Digester newDigester(final Class<?> clazz) { DigesterLoader loader = newLoader(new FromAnnotationsRuleModule() { @Override protected void configureRules() { bindRulesFrom(clazz); } }); loader.setNamespaceAware(true); ConvertUtils.register(new DateTimeConverter(), DateTime.class); ConvertUtils.register(new LanguageConverter(), Language.class); ConvertUtils.register(new PeriodConverter(), Period.class); ConvertUtils.register(new UriConverter(), URI.class); return loader.newDigester(); } }