View Javadoc

1   /**
2    *
3    * Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
4    *
5    * ====================================================================
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   * ====================================================================
18   */
19  package org.jclouds.scriptbuilder.domain;
20  
21  import static com.google.common.base.Preconditions.checkNotNull;
22  import static com.google.common.base.Preconditions.checkState;
23  import static org.jclouds.scriptbuilder.domain.Statements.interpret;
24  
25  import java.util.Collections;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Map.Entry;
29  import java.util.regex.Pattern;
30  
31  import com.google.common.collect.ImmutableList;
32  import com.google.common.collect.Iterables;
33  import com.google.common.collect.Lists;
34  import com.google.common.collect.Maps;
35  
36  /**
37   * Creates a run script
38   * 
39   * @author Adrian Cole
40   */
41  public class AppendFile implements Statement {
42     public static final String MARKER = "END_OF_FILE";
43  
44     final String path;
45     final Iterable<String> lines;
46     final String marker;
47  
48     public AppendFile(String path, Iterable<String> lines) {
49        this(path, lines, MARKER);
50     }
51  
52     public AppendFile(String path, Iterable<String> lines, String marker) {
53        this.path = checkNotNull(path, "path");
54        this.lines = checkNotNull(lines, "lines");
55        this.marker = checkNotNull(marker, "marker");
56        checkState(Iterables.size(lines) > 0, "you must pass something to execute");
57     }
58  
59     public static String escapeVarTokens(String toEscape, OsFamily family) {
60        Map<String, String> inputToEscape = Maps.newHashMap();
61        for (ShellToken token : ImmutableList.of(ShellToken.VARL, ShellToken.VARR)) {
62           if (!token.to(family).equals("")) {
63              String tokenS = "{" + token.toString().toLowerCase() + "}";
64              inputToEscape.put(tokenS, "{escvar}" + tokenS);
65           }
66        }
67        for (Entry<String, String> entry : inputToEscape.entrySet()) {
68           toEscape = toEscape.replace(entry.getKey(), entry.getValue());
69        }
70        return toEscape;
71     }
72  
73     @Override
74     public Iterable<String> functionDependencies(OsFamily family) {
75        return Collections.emptyList();
76     }
77  
78     @Override
79     public String render(OsFamily family) {
80        List<Statement> statements = Lists.newArrayList();
81        if (family == OsFamily.UNIX) {
82           StringBuilder builder = new StringBuilder();
83           hereFile(path, builder);
84           statements.add(interpret(builder.toString()));
85        } else {
86           for (String line : lines) {
87              statements.add(appendToFile(line, path, family));
88           }
89        }
90        return new StatementList(statements).render(family);
91     }
92  
93     private void hereFile(String path, StringBuilder builder) {
94        builder.append("cat >> ").append(path).append(" <<'").append(marker).append("'\n");
95        for (String line : lines) {
96           builder.append(line).append("\n");
97        }
98        builder.append(marker).append("\n");
99     }
100 
101    private Statement appendToFile(String line, String path, OsFamily family) {
102       String quote = "";
103       if (!ShellToken.VQ.to(family).equals("")) {
104          quote = "'";
105       } else {
106          line = escapeVarTokens(line, family);
107       }
108       return interpret(addSpaceToEnsureWeDontAccidentallyRedirectFd(String.format("echo %s%s%s>>%s{lf}", quote, line,
109                quote, path)));
110    }
111 
112    public static final Pattern REDIRECT_FD_PATTERN = Pattern.compile(".*[0-2]>>.*");
113 
114    static String addSpaceToEnsureWeDontAccidentallyRedirectFd(String line) {
115       return REDIRECT_FD_PATTERN.matcher(line).matches() ? line.replace(">>", " >>") : line;
116    }
117 
118 }