001 /*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2014 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * SonarQube is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * SonarQube is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
019 */
020 package org.sonar.api.utils;
021
022 import com.google.common.annotations.VisibleForTesting;
023 import com.google.common.base.Preconditions;
024 import com.google.common.base.Throwables;
025 import com.google.common.collect.Lists;
026 import com.google.common.collect.Maps;
027 import com.google.common.io.Files;
028 import org.sonar.api.BatchComponent;
029 import org.sonar.api.ServerComponent;
030
031 import java.io.File;
032 import java.io.IOException;
033 import java.net.URI;
034 import java.nio.charset.Charset;
035 import java.util.List;
036 import java.util.Locale;
037 import java.util.Map;
038
039 /**
040 * Reads different types of URI. Supported schemes are http and file.
041 *
042 * @since 3.2
043 */
044 public class UriReader implements BatchComponent, ServerComponent {
045
046 private final Map<String, SchemeProcessor> processorsByScheme = Maps.newHashMap();
047
048 public UriReader(SchemeProcessor[] processors) {
049 List<SchemeProcessor> allProcessors = Lists.asList(new FileProcessor(), processors);
050 for (SchemeProcessor processor : allProcessors) {
051 for (String scheme : processor.getSupportedSchemes()) {
052 processorsByScheme.put(scheme.toLowerCase(Locale.ENGLISH), processor);
053 }
054 }
055 }
056
057 /**
058 * Reads all bytes from uri. It throws an unchecked exception if an error occurs.
059 */
060 public byte[] readBytes(URI uri) {
061 return searchForSupportedProcessor(uri).readBytes(uri);
062 }
063
064 /**
065 * Reads all characters from uri, using the given character set.
066 * It throws an unchecked exception if an error occurs.
067 */
068 public String readString(URI uri, Charset charset) {
069 return searchForSupportedProcessor(uri).readString(uri, charset);
070 }
071
072 /**
073 * Returns a detailed description of the given uri. For example HTTP URIs are completed
074 * with the configured HTTP proxy.
075 */
076 public String description(URI uri) {
077 SchemeProcessor reader = searchForSupportedProcessor(uri);
078
079 return reader.description(uri);
080 }
081
082 @VisibleForTesting
083 SchemeProcessor searchForSupportedProcessor(URI uri) {
084 SchemeProcessor processor = processorsByScheme.get(uri.getScheme().toLowerCase(Locale.ENGLISH));
085 Preconditions.checkArgument(processor != null, "URI schema is not supported: " + uri.getScheme());
086 return processor;
087 }
088
089 abstract static class SchemeProcessor {
090 abstract String[] getSupportedSchemes();
091
092 abstract byte[] readBytes(URI uri);
093
094 abstract String readString(URI uri, Charset charset);
095
096 abstract String description(URI uri);
097 }
098
099
100 /**
101 * This implementation is not exposed in API and is kept private.
102 */
103 private static class FileProcessor extends SchemeProcessor {
104
105 @Override
106 public String[] getSupportedSchemes() {
107 return new String[]{"file"};
108 }
109
110 @Override
111 byte[] readBytes(URI uri) {
112 try {
113 return Files.toByteArray(new File(uri));
114 } catch (IOException e) {
115 throw Throwables.propagate(e);
116 }
117 }
118
119 @Override
120 String readString(URI uri, Charset charset) {
121 try {
122 return Files.toString(new File(uri), charset);
123 } catch (IOException e) {
124 throw Throwables.propagate(e);
125 }
126 }
127
128 @Override
129 String description(URI uri) {
130 return new File(uri).getAbsolutePath();
131 }
132 }
133 }