/*******************************************************************************
* Copyright (c) 2012-2015 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.api.core.rest;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.UnauthorizedException;
import org.eclipse.che.api.core.rest.shared.dto.Link;
import org.eclipse.che.api.core.rest.shared.dto.ServiceDescriptor;
import org.eclipse.che.dto.server.DtoFactory;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* Provides basic functionality to access remote {@link Service Service}. Basically provides next information about {@code Service}:
* <ul>
* <li>URL of {@code Service}</li>
* <li>Version of API</li>
* <li>Optional description of {@code Service}</li>
* <li>Set of {@link org.eclipse.che.api.core.rest.shared.dto.Link Link} to access {@code Service} functionality</li>
* </ul>
*
* @author andrew00x
* @see Service
* @see #getLinks()
*/
public class RemoteServiceDescriptor {
protected final String baseUrl;
private final URL baseUrlURL;
// will be initialized when it is needed
private volatile ServiceDescriptor serviceDescriptor;
/**
* Creates new descriptor of remote RESTful service.
*
* @throws java.lang.IllegalArgumentException
* if URL is invalid
*/
public RemoteServiceDescriptor(String baseUrl) throws IllegalArgumentException {
this.baseUrl = baseUrl;
try {
baseUrlURL = new URL(baseUrl);
final String protocol = baseUrlURL.getProtocol();
if (!(protocol.equals("http") || protocol.equals("https"))) {
throw new IllegalArgumentException(String.format("Invalid URL: %s", baseUrl));
}
} catch (MalformedURLException e) {
throw new IllegalArgumentException(String.format("Invalid URL: %s", baseUrl));
}
}
public String getBaseUrl() {
return baseUrl;
}
/** @see ServiceDescriptor#getLinks() */
public List<Link> getLinks() throws ServerException, IOException {
final List<Link> links = getServiceDescriptor().getLinks();
// always copy list and links itself!
final List<Link> copy = new ArrayList<>(links.size());
for (Link link : links) {
copy.add(DtoFactory.getInstance().clone(link));
}
return copy;
}
public Link getLink(String rel) throws ServerException, IOException {
final Link link = getServiceDescriptor().getLink(rel);
return link == null ? null : DtoFactory.getInstance().clone(link);
}
public ServiceDescriptor getServiceDescriptor() throws IOException, ServerException {
ServiceDescriptor myServiceDescriptor = serviceDescriptor;
if (myServiceDescriptor == null) {
synchronized (this) {
myServiceDescriptor = serviceDescriptor;
if (myServiceDescriptor == null) {
try {
myServiceDescriptor = serviceDescriptor = HttpJsonHelper.options(getServiceDescriptorClass(), baseUrl);
} catch (NotFoundException | ConflictException | UnauthorizedException | ForbiddenException e) {
throw new ServerException(e.getServiceError());
}
}
}
}
return myServiceDescriptor;
}
protected Class<? extends ServiceDescriptor> getServiceDescriptorClass() {
return ServiceDescriptor.class;
}
/** Checks service availability. */
public boolean isAvailable() {
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection)baseUrlURL.openConnection();
conn.setConnectTimeout(3 * 1000);
conn.setReadTimeout(3 * 1000);
conn.setRequestMethod("OPTIONS");
return 200 == conn.getResponseCode();
} catch (IOException e) {
return false;
} finally {
if (conn != null) {
conn.disconnect();
}
}
}
}